Coverage for dcim/graphql/types.py: 83%

231 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from typing import TYPE_CHECKING, Annotated 

2 

3import strawberry 

4import strawberry_django 

5from django.db.models import Func, IntegerField, Prefetch 

6 

7from circuits.models import CircuitTermination 

8from core.graphql.mixins import ChangelogMixin 

9from dcim import models 

10from dcim.choices import CableEndChoices 

11from extras.graphql.mixins import ConfigContextMixin, ContactsMixin, ImageAttachmentsMixin 

12from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin 

13from netbox.graphql.optimization import build_gfk_prefetch 

14from netbox.graphql.scalars import BigInt 

15from netbox.graphql.types import ( 

16 BaseObjectType, 

17 LtreeNodeMixin, 

18 NestedLtreeGroupObjectType, 

19 NetBoxObjectType, 

20 OrganizationalObjectType, 

21 PrimaryObjectType, 

22 register_type, 

23) 

24from users.graphql.mixins import OwnerMixin 

25from utilities.querysets import RestrictedPrefetch 

26from virtualization.models import Cluster, VMInterface 

27 

28from .filters import * 

29from .mixins import CabledObjectMixin, PathEndpointMixin 

30 

31if TYPE_CHECKING: 31 ↛ 32line 31 didn't jump to line 32 because the condition on line 31 was never true

32 from circuits.graphql.types import CircuitTerminationType 

33 from extras.graphql.types import ConfigTemplateType 

34 from ipam.graphql.types import ( 

35 ASNType, 

36 IPAddressType, 

37 PrefixType, 

38 ServiceType, 

39 VLANTranslationPolicyType, 

40 VLANType, 

41 VRFType, 

42 ) 

43 from tenancy.graphql.types import TenantType 

44 from users.graphql.types import UserType 

45 from virtualization.graphql.types import ClusterType, VirtualMachineType, VMInterfaceType 

46 from vpn.graphql.types import L2VPNTerminationType 

47 from wireless.graphql.types import WirelessLANType, WirelessLinkType 

48 

49__all__ = ( 

50 'CableBundleType', 

51 'CableType', 

52 'ComponentType', 

53 'ConsolePortTemplateType', 

54 'ConsolePortType', 

55 'ConsoleServerPortTemplateType', 

56 'ConsoleServerPortType', 

57 'CoolingFeedType', 

58 'CoolingIntakeTemplateType', 

59 'CoolingIntakeType', 

60 'CoolingOutflowTemplateType', 

61 'CoolingOutflowType', 

62 'CoolingSourceType', 

63 'DeviceBayTemplateType', 

64 'DeviceBayType', 

65 'DeviceRoleType', 

66 'DeviceType', 

67 'DeviceTypeType', 

68 'FrontPortTemplateType', 

69 'FrontPortType', 

70 'InterfaceTemplateType', 

71 'InterfaceType', 

72 'InventoryItemRoleType', 

73 'InventoryItemTemplateType', 

74 'InventoryItemType', 

75 'LocationType', 

76 'MACAddressType', 

77 'ManufacturerType', 

78 'ModularComponentType', 

79 'ModuleBayTemplateType', 

80 'ModuleBayType', 

81 'ModuleBayTypeType', 

82 'ModuleType', 

83 'ModuleTypeProfileType', 

84 'ModuleTypeType', 

85 'PlatformType', 

86 'PowerFeedType', 

87 'PowerOutletTemplateType', 

88 'PowerOutletType', 

89 'PowerPanelType', 

90 'PowerPortTemplateType', 

91 'PowerPortType', 

92 'RackGroupType', 

93 'RackReservationType', 

94 'RackRoleType', 

95 'RackType', 

96 'RackTypeType', 

97 'RearPortTemplateType', 

98 'RearPortType', 

99 'RegionType', 

100 'SiteGroupType', 

101 'SiteType', 

102 'VirtualChassisType', 

103 'VirtualDeviceContextType', 

104) 

105 

106 

107# 

108# Cable termination prefetching 

109# 

110 

111# The concrete models which may terminate a cable, mirroring dcim.constants.CABLE_TERMINATION_MODELS 

112_CABLE_TERMINATION_MODELS = ( 

113 CircuitTermination, 

114 models.ConsolePort, 

115 models.ConsoleServerPort, 

116 models.FrontPort, 

117 models.Interface, 

118 models.PowerFeed, 

119 models.PowerOutlet, 

120 models.PowerPort, 

121 models.RearPort, 

122) 

123 

124_termination_gfk_prefetch = build_gfk_prefetch('termination', _CABLE_TERMINATION_MODELS) 

125 

126 

127def _cable_terminations_prefetch(side, to_attr): 

128 """ 

129 Return a callable which builds a selection-aware Prefetch of a cable's terminations for the 

130 given cable end. 

131 

132 Each end is prefetched under its own `to_attr`: two prefetches of the same relation cannot be 

133 merged by the query optimizer, so a shared lookup would break any query selecting both ends. 

134 """ 

135 def prefetch(info): 

136 return Prefetch( 

137 'terminations', 

138 queryset=models.CableTermination.objects.filter(cable_end=side).prefetch_related( 

139 _termination_gfk_prefetch(info) 

140 ), 

141 to_attr=to_attr, 

142 ) 

143 

144 return prefetch 

145 

146 

147def _resolve_cable_terminations(cable, side, to_attr): 

148 """ 

149 Return the terminating objects for the given cable end, using the prefetched terminations if 

150 available and falling back to the model property otherwise. 

151 """ 

152 if (terminations := getattr(cable, to_attr, None)) is not None: 

153 return [ct.termination for ct in terminations] 

154 

155 return cable._get_x_terminations(side) 

156 

157 

158# 

159# Base types 

160# 

161 

162 

163@strawberry.type 

164class ComponentType(OwnerMixin, NetBoxObjectType): 

165 """ 

166 Base type for device/VM components 

167 """ 

168 device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] 

169 

170 

171@strawberry.type 

172class ModularComponentType(ComponentType): 

173 module: Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')] | None 

174 

175 

176@strawberry.type 

177class ComponentTemplateType(ChangelogMixin, BaseObjectType): 

178 """ 

179 Base type for device/VM components 

180 """ 

181 device_type: Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')] 

182 

183 

184@strawberry.type 

185class ModularComponentTemplateType(ComponentTemplateType): 

186 """ 

187 Base type for ComponentTemplateModel which supports optional assignment to a ModuleType. 

188 """ 

189 device_type: Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')] | None 

190 module_type: Annotated["ModuleTypeType", strawberry.lazy('dcim.graphql.types')] | None 

191 

192# 

193# Model types 

194# 

195 

196 

197@register_type( 

198 models.CableBundle, 

199 fields='__all__', 

200 filters=CableBundleFilter, 

201 pagination=True 

202) 

203class CableBundleType(PrimaryObjectType): 

204 cables: list[Annotated['CableType', strawberry.lazy('dcim.graphql.types')]] 

205 

206 

207@register_type( 

208 models.CableTermination, 

209 exclude=['termination_type', 'termination_id', '_device', '_rack', '_location', '_site'], 

210 filters=CableTerminationFilter, 

211 pagination=True 

212) 

213class CableTerminationType(NetBoxObjectType): 

214 cable: Annotated['CableType', strawberry.lazy('dcim.graphql.types')] | None 

215 

216 @strawberry_django.field( 

217 prefetch_related=_termination_gfk_prefetch, 

218 only=['termination_type', 'termination_id'], 

219 ) 

220 def termination(self) -> Annotated[ 

221 Annotated['CircuitTerminationType', strawberry.lazy('circuits.graphql.types')] 

222 | Annotated['ConsolePortType', strawberry.lazy('dcim.graphql.types')] 

223 | Annotated['ConsoleServerPortType', strawberry.lazy('dcim.graphql.types')] 

224 | Annotated['FrontPortType', strawberry.lazy('dcim.graphql.types')] 

225 | Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] 

226 | Annotated['PowerFeedType', strawberry.lazy('dcim.graphql.types')] 

227 | Annotated['PowerOutletType', strawberry.lazy('dcim.graphql.types')] 

228 | Annotated['PowerPortType', strawberry.lazy('dcim.graphql.types')] 

229 | Annotated['RearPortType', strawberry.lazy('dcim.graphql.types')], 

230 strawberry.union('CableTerminationTerminationType'), 

231 ] | None: 

232 return self.termination 

233 

234 

235@register_type( 

236 models.Cable, 

237 fields='__all__', 

238 filters=CableFilter, 

239 pagination=True 

240) 

241class CableType(PrimaryObjectType): 

242 color: str 

243 tenant: Annotated['TenantType', strawberry.lazy('tenancy.graphql.types')] | None 

244 bundle: Annotated['CableBundleType', strawberry.lazy('dcim.graphql.types')] | None 

245 

246 terminations: list[CableTerminationType] 

247 

248 @strawberry_django.field( 

249 prefetch_related=_cable_terminations_prefetch(CableEndChoices.SIDE_A, '_prefetched_a_terminations'), 

250 ) 

251 def a_terminations(self) -> list[Annotated[ 

252 Annotated['CircuitTerminationType', strawberry.lazy('circuits.graphql.types')] 

253 | Annotated['ConsolePortType', strawberry.lazy('dcim.graphql.types')] 

254 | Annotated['ConsoleServerPortType', strawberry.lazy('dcim.graphql.types')] 

255 | Annotated['FrontPortType', strawberry.lazy('dcim.graphql.types')] 

256 | Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] 

257 | Annotated['PowerFeedType', strawberry.lazy('dcim.graphql.types')] 

258 | Annotated['PowerOutletType', strawberry.lazy('dcim.graphql.types')] 

259 | Annotated['PowerPortType', strawberry.lazy('dcim.graphql.types')] 

260 | Annotated['RearPortType', strawberry.lazy('dcim.graphql.types')], 

261 strawberry.union('CableTerminationTerminationType'), 

262 ]]: 

263 return _resolve_cable_terminations(self, CableEndChoices.SIDE_A, '_prefetched_a_terminations') 

264 

265 @strawberry_django.field( 

266 prefetch_related=_cable_terminations_prefetch(CableEndChoices.SIDE_B, '_prefetched_b_terminations'), 

267 ) 

268 def b_terminations(self) -> list[Annotated[ 

269 Annotated['CircuitTerminationType', strawberry.lazy('circuits.graphql.types')] 

270 | Annotated['ConsolePortType', strawberry.lazy('dcim.graphql.types')] 

271 | Annotated['ConsoleServerPortType', strawberry.lazy('dcim.graphql.types')] 

272 | Annotated['FrontPortType', strawberry.lazy('dcim.graphql.types')] 

273 | Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] 

274 | Annotated['PowerFeedType', strawberry.lazy('dcim.graphql.types')] 

275 | Annotated['PowerOutletType', strawberry.lazy('dcim.graphql.types')] 

276 | Annotated['PowerPortType', strawberry.lazy('dcim.graphql.types')] 

277 | Annotated['RearPortType', strawberry.lazy('dcim.graphql.types')], 

278 strawberry.union('CableTerminationTerminationType'), 

279 ]]: 

280 return _resolve_cable_terminations(self, CableEndChoices.SIDE_B, '_prefetched_b_terminations') 

281 

282 

283@register_type( 

284 models.ConsolePort, 

285 exclude=['_path'], 

286 filters=ConsolePortFilter, 

287 pagination=True 

288) 

289class ConsolePortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin): 

290 pass 

291 

292 

293@register_type( 

294 models.ConsolePortTemplate, 

295 fields='__all__', 

296 filters=ConsolePortTemplateFilter, 

297 pagination=True 

298) 

299class ConsolePortTemplateType(ModularComponentTemplateType): 

300 pass 

301 

302 

303@register_type( 

304 models.ConsoleServerPort, 

305 exclude=['_path'], 

306 filters=ConsoleServerPortFilter, 

307 pagination=True 

308) 

309class ConsoleServerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin): 

310 pass 

311 

312 

313@register_type( 

314 models.ConsoleServerPortTemplate, 

315 fields='__all__', 

316 filters=ConsoleServerPortTemplateFilter, 

317 pagination=True 

318) 

319class ConsoleServerPortTemplateType(ModularComponentTemplateType): 

320 pass 

321 

322 

323@register_type( 

324 models.Device, 

325 fields='__all__', 

326 filters=DeviceFilter, 

327 pagination=True 

328) 

329class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType): 

330 console_port_count: BigInt 

331 console_server_port_count: BigInt 

332 power_port_count: BigInt 

333 power_outlet_count: BigInt 

334 cooling_intake_count: BigInt 

335 cooling_outflow_count: BigInt 

336 interface_count: BigInt 

337 front_port_count: BigInt 

338 rear_port_count: BigInt 

339 device_bay_count: BigInt 

340 module_bay_count: BigInt 

341 inventory_item_count: BigInt 

342 config_template: Annotated["ConfigTemplateType", strawberry.lazy('extras.graphql.types')] | None 

343 device_type: Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')] 

344 role: Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')] 

345 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

346 platform: Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')] | None 

347 site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] 

348 location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None 

349 rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')] | None 

350 primary_ip4: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None 

351 primary_ip6: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None 

352 oob_ip: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None 

353 cluster: Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')] | None 

354 virtual_chassis: Annotated["VirtualChassisType", strawberry.lazy('dcim.graphql.types')] | None 

355 

356 virtual_machines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]] 

357 modules: list[Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')]] 

358 interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] 

359 rearports: list[Annotated["RearPortType", strawberry.lazy('dcim.graphql.types')]] 

360 consoleports: list[Annotated["ConsolePortType", strawberry.lazy('dcim.graphql.types')]] 

361 powerports: list[Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')]] 

362 coolingintakes: list[Annotated["CoolingIntakeType", strawberry.lazy('dcim.graphql.types')]] 

363 cabletermination_set: list[Annotated["CableTerminationType", strawberry.lazy('dcim.graphql.types')]] 

364 consoleserverports: list[Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')]] 

365 poweroutlets: list[Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')]] 

366 coolingoutflows: list[Annotated["CoolingOutflowType", strawberry.lazy('dcim.graphql.types')]] 

367 frontports: list[Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')]] 

368 devicebays: list[Annotated["DeviceBayType", strawberry.lazy('dcim.graphql.types')]] 

369 modulebays: list[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] 

370 services: list[Annotated["ServiceType", strawberry.lazy('ipam.graphql.types')]] 

371 inventoryitems: list[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] 

372 vdcs: list[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]] 

373 

374 @strawberry_django.field(prefetch_related='vc_master_for') 

375 def vc_master_for(self) -> Annotated["VirtualChassisType", strawberry.lazy('dcim.graphql.types')] | None: 

376 return self.vc_master_for if hasattr(self, 'vc_master_for') else None 

377 

378 @strawberry_django.field(prefetch_related='parent_bay') 

379 def parent_bay(self) -> Annotated["DeviceBayType", strawberry.lazy('dcim.graphql.types')] | None: 

380 return self.parent_bay if hasattr(self, 'parent_bay') else None 

381 

382 

383@register_type( 

384 models.DeviceBay, 

385 fields='__all__', 

386 filters=DeviceBayFilter, 

387 pagination=True 

388) 

389class DeviceBayType(ComponentType): 

390 installed_device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None 

391 

392 

393@register_type( 

394 models.DeviceBayTemplate, 

395 fields='__all__', 

396 filters=DeviceBayTemplateFilter, 

397 pagination=True 

398) 

399class DeviceBayTemplateType(ComponentTemplateType): 

400 pass 

401 

402 

403@register_type( 

404 models.InventoryItemTemplate, 

405 exclude=['component_type', 'component_id', 'parent', 'path'], 

406 filters=InventoryItemTemplateFilter, 

407 pagination=True 

408) 

409class InventoryItemTemplateType(LtreeNodeMixin, ComponentTemplateType): 

410 role: Annotated['InventoryItemRoleType', strawberry.lazy('dcim.graphql.types')] | None 

411 manufacturer: Annotated['ManufacturerType', strawberry.lazy('dcim.graphql.types')] 

412 

413 @strawberry_django.field(prefetch_related='parent', only=['parent_id']) 

414 def parent(self) -> Annotated['InventoryItemTemplateType', strawberry.lazy('dcim.graphql.types')] | None: 

415 return self.parent 

416 

417 child_items: list[Annotated['InventoryItemTemplateType', strawberry.lazy('dcim.graphql.types')]] 

418 

419 @strawberry_django.field( 

420 prefetch_related=build_gfk_prefetch( 

421 'component', 

422 [ 

423 models.ConsolePortTemplate, 

424 models.ConsoleServerPortTemplate, 

425 models.FrontPortTemplate, 

426 models.InterfaceTemplate, 

427 models.PowerOutletTemplate, 

428 models.PowerPortTemplate, 

429 models.RearPortTemplate, 

430 ], 

431 ), 

432 only=['component_type', 'component_id'], 

433 ) 

434 def component(self) -> Annotated[ 

435 Annotated['ConsolePortTemplateType', strawberry.lazy('dcim.graphql.types')] 

436 | Annotated['ConsoleServerPortTemplateType', strawberry.lazy('dcim.graphql.types')] 

437 | Annotated['FrontPortTemplateType', strawberry.lazy('dcim.graphql.types')] 

438 | Annotated['InterfaceTemplateType', strawberry.lazy('dcim.graphql.types')] 

439 | Annotated['PowerOutletTemplateType', strawberry.lazy('dcim.graphql.types')] 

440 | Annotated['PowerPortTemplateType', strawberry.lazy('dcim.graphql.types')] 

441 | Annotated['RearPortTemplateType', strawberry.lazy('dcim.graphql.types')], 

442 strawberry.union('InventoryItemTemplateComponentType'), 

443 ] | None: 

444 return self.component 

445 

446 

447@register_type( 

448 models.DeviceRole, 

449 exclude=['path', 'sort_path'], 

450 filters=DeviceRoleFilter, 

451 pagination=True 

452) 

453class DeviceRoleType(NestedLtreeGroupObjectType): 

454 parent: Annotated['DeviceRoleType', strawberry.lazy('dcim.graphql.types')] | None 

455 children: list[Annotated['DeviceRoleType', strawberry.lazy('dcim.graphql.types')]] 

456 color: str 

457 config_template: Annotated["ConfigTemplateType", strawberry.lazy('extras.graphql.types')] | None 

458 

459 virtual_machines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]] 

460 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

461 

462 

463@register_type( 

464 models.DeviceType, 

465 fields='__all__', 

466 filters=DeviceTypeFilter, 

467 pagination=True 

468) 

469class DeviceTypeType(PrimaryObjectType): 

470 console_port_template_count: BigInt 

471 console_server_port_template_count: BigInt 

472 power_port_template_count: BigInt 

473 power_outlet_template_count: BigInt 

474 cooling_intake_template_count: BigInt 

475 cooling_outflow_template_count: BigInt 

476 interface_template_count: BigInt 

477 front_port_template_count: BigInt 

478 rear_port_template_count: BigInt 

479 device_bay_template_count: BigInt 

480 module_bay_template_count: BigInt 

481 inventory_item_template_count: BigInt 

482 device_count: BigInt 

483 front_image: strawberry_django.fields.types.DjangoImageType | None 

484 rear_image: strawberry_django.fields.types.DjangoImageType | None 

485 manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] 

486 default_platform: Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')] | None 

487 

488 frontporttemplates: list[Annotated["FrontPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

489 modulebaytemplates: list[Annotated["ModuleBayTemplateType", strawberry.lazy('dcim.graphql.types')]] 

490 instances: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

491 poweroutlettemplates: list[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]] 

492 powerporttemplates: list[Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

493 coolingoutflowtemplates: list[Annotated["CoolingOutflowTemplateType", strawberry.lazy('dcim.graphql.types')]] 

494 coolingintaketemplates: list[Annotated["CoolingIntakeTemplateType", strawberry.lazy('dcim.graphql.types')]] 

495 inventoryitemtemplates: list[Annotated["InventoryItemTemplateType", strawberry.lazy('dcim.graphql.types')]] 

496 rearporttemplates: list[Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

497 consoleserverporttemplates: list[Annotated["ConsoleServerPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

498 interfacetemplates: list[Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')]] 

499 devicebaytemplates: list[Annotated["DeviceBayTemplateType", strawberry.lazy('dcim.graphql.types')]] 

500 consoleporttemplates: list[Annotated["ConsolePortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

501 

502 

503@register_type( 

504 models.FrontPort, 

505 fields='__all__', 

506 filters=FrontPortFilter, 

507 pagination=True 

508) 

509class FrontPortType(ModularComponentType, CabledObjectMixin): 

510 color: str 

511 

512 mappings: list[Annotated["PortMappingType", strawberry.lazy('dcim.graphql.types')]] 

513 

514 

515@register_type( 

516 models.FrontPortTemplate, 

517 fields='__all__', 

518 filters=FrontPortTemplateFilter, 

519 pagination=True 

520) 

521class FrontPortTemplateType(ModularComponentTemplateType): 

522 color: str 

523 

524 mappings: list[Annotated["PortMappingTemplateType", strawberry.lazy('dcim.graphql.types')]] 

525 

526 

527@register_type( 

528 models.MACAddress, 

529 exclude=['assigned_object_type', 'assigned_object_id'], 

530 filters=MACAddressFilter, 

531 pagination=True 

532) 

533class MACAddressType(PrimaryObjectType): 

534 mac_address: str 

535 

536 @strawberry_django.field( 

537 prefetch_related=build_gfk_prefetch( 

538 'assigned_object', 

539 [ 

540 models.Interface, 

541 VMInterface, 

542 ], 

543 ), 

544 only=['assigned_object_type', 'assigned_object_id'], 

545 ) 

546 def assigned_object(self) -> Annotated[ 

547 Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] 

548 | Annotated['VMInterfaceType', strawberry.lazy('virtualization.graphql.types')], 

549 strawberry.union('MACAddressAssignmentType'), 

550 ] | None: 

551 return self.assigned_object 

552 

553 

554@register_type( 

555 models.Interface, 

556 exclude=['_path'], 

557 filters=InterfaceFilter, 

558 pagination=True 

559) 

560class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin): 

561 _name: str 

562 speed: BigInt | None 

563 wwn: str | None 

564 parent: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None 

565 bridge: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None 

566 lag: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None 

567 wireless_link: Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')] | None 

568 untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None 

569 vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None 

570 primary_mac_address: Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')] | None 

571 qinq_svlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None 

572 vlan_translation_policy: Annotated["VLANTranslationPolicyType", strawberry.lazy('ipam.graphql.types')] | None 

573 l2vpn_termination: Annotated["L2VPNTerminationType", strawberry.lazy('vpn.graphql.types')] | None 

574 

575 vdcs: list[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]] 

576 tagged_vlans: list[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]] 

577 bridge_interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] 

578 wireless_lans: list[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]] 

579 member_interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] 

580 child_interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] 

581 mac_addresses: list[Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')]] 

582 

583 

584@register_type( 

585 models.InterfaceTemplate, 

586 fields='__all__', 

587 filters=InterfaceTemplateFilter, 

588 pagination=True 

589) 

590class InterfaceTemplateType(ModularComponentTemplateType): 

591 _name: str 

592 parent: Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')] | None 

593 bridge: Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')] | None 

594 

595 bridge_interfaces: list[Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')]] 

596 child_interfaces: list[Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')]] 

597 

598 

599@register_type( 

600 models.InventoryItem, 

601 exclude=['component_type', 'component_id', 'parent', 'path'], 

602 filters=InventoryItemFilter, 

603 pagination=True 

604) 

605class InventoryItemType(LtreeNodeMixin, ComponentType): 

606 role: Annotated['InventoryItemRoleType', strawberry.lazy('dcim.graphql.types')] | None 

607 manufacturer: Annotated['ManufacturerType', strawberry.lazy('dcim.graphql.types')] | None 

608 

609 child_items: list[Annotated['InventoryItemType', strawberry.lazy('dcim.graphql.types')]] 

610 

611 @strawberry_django.field(prefetch_related='parent', only=['parent_id']) 

612 def parent(self) -> Annotated['InventoryItemType', strawberry.lazy('dcim.graphql.types')] | None: 

613 return self.parent 

614 

615 @strawberry_django.field( 

616 prefetch_related=build_gfk_prefetch( 

617 'component', 

618 [ 

619 models.ConsolePort, 

620 models.ConsoleServerPort, 

621 models.FrontPort, 

622 models.Interface, 

623 models.PowerOutlet, 

624 models.PowerPort, 

625 models.RearPort, 

626 ], 

627 ), 

628 only=['component_type', 'component_id'], 

629 ) 

630 def component(self) -> Annotated[ 

631 Annotated['ConsolePortType', strawberry.lazy('dcim.graphql.types')] 

632 | Annotated['ConsoleServerPortType', strawberry.lazy('dcim.graphql.types')] 

633 | Annotated['FrontPortType', strawberry.lazy('dcim.graphql.types')] 

634 | Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] 

635 | Annotated['PowerOutletType', strawberry.lazy('dcim.graphql.types')] 

636 | Annotated['PowerPortType', strawberry.lazy('dcim.graphql.types')] 

637 | Annotated['RearPortType', strawberry.lazy('dcim.graphql.types')], 

638 strawberry.union('InventoryItemComponentType'), 

639 ] | None: 

640 return self.component 

641 

642 

643@register_type( 

644 models.InventoryItemRole, 

645 fields='__all__', 

646 filters=InventoryItemRoleFilter, 

647 pagination=True 

648) 

649class InventoryItemRoleType(OrganizationalObjectType): 

650 color: str 

651 

652 inventory_items: list[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] 

653 inventory_item_templates: list[Annotated["InventoryItemTemplateType", strawberry.lazy('dcim.graphql.types')]] 

654 

655 

656@register_type( 

657 models.Location, 

658 # fields='__all__', 

659 exclude=['parent', 'path', 'sort_path'], # bug - temp 

660 filters=LocationFilter, 

661 pagination=True 

662) 

663class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NestedLtreeGroupObjectType): 

664 site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] 

665 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

666 parent: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None 

667 

668 powerpanel_set: list[Annotated["PowerPanelType", strawberry.lazy('dcim.graphql.types')]] 

669 cabletermination_set: list[Annotated["CableTerminationType", strawberry.lazy('dcim.graphql.types')]] 

670 racks: list[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]] 

671 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

672 children: list[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]] 

673 

674 @strawberry_django.field( 

675 prefetch_related=lambda info: RestrictedPrefetch( 

676 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() 

677 ), 

678 ) 

679 def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: 

680 return self.cluster_set.all() 

681 

682 @strawberry_django.field( 

683 prefetch_related=lambda info: RestrictedPrefetch( 

684 'circuit_terminations', info.context.request.user, 'view', 

685 queryset=CircuitTermination.objects.all() 

686 ), 

687 ) 

688 def circuit_terminations(self) -> list[ 

689 Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] 

690 ]: 

691 return self.circuit_terminations.all() 

692 

693 

694@register_type( 

695 models.Manufacturer, 

696 fields='__all__', 

697 filters=ManufacturerFilter, 

698 pagination=True 

699) 

700class ManufacturerType(OrganizationalObjectType, ContactsMixin): 

701 

702 platforms: list[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]] 

703 device_types: list[Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')]] 

704 inventory_item_templates: list[Annotated["InventoryItemTemplateType", strawberry.lazy('dcim.graphql.types')]] 

705 inventory_items: list[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] 

706 module_types: list[Annotated["ModuleTypeType", strawberry.lazy('dcim.graphql.types')]] 

707 

708 

709@register_type( 

710 models.Module, 

711 fields='__all__', 

712 filters=ModuleFilter, 

713 pagination=True 

714) 

715class ModuleType(PrimaryObjectType): 

716 device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] 

717 module_bay: Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')] 

718 module_type: Annotated["ModuleTypeType", strawberry.lazy('dcim.graphql.types')] 

719 

720 interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] 

721 powerports: list[Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')]] 

722 coolingintakes: list[Annotated["CoolingIntakeType", strawberry.lazy('dcim.graphql.types')]] 

723 consoleserverports: list[Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')]] 

724 consoleports: list[Annotated["ConsolePortType", strawberry.lazy('dcim.graphql.types')]] 

725 poweroutlets: list[Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')]] 

726 coolingoutflows: list[Annotated["CoolingOutflowType", strawberry.lazy('dcim.graphql.types')]] 

727 rearports: list[Annotated["RearPortType", strawberry.lazy('dcim.graphql.types')]] 

728 frontports: list[Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')]] 

729 

730 

731@register_type( 

732 models.ModuleBay, 

733 # fields='__all__', 

734 exclude=['parent', 'path', 'sort_path'], 

735 filters=ModuleBayFilter, 

736 pagination=True 

737) 

738class ModuleBayType(LtreeNodeMixin, ModularComponentType): 

739 

740 installed_module: Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')] | None 

741 children: list[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] 

742 module_bay_types: list[Annotated["ModuleBayTypeType", strawberry.lazy('dcim.graphql.types')]] 

743 

744 @strawberry_django.field(prefetch_related='parent', only=['parent_id']) 

745 def parent(self) -> Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')] | None: 

746 return self.parent 

747 

748 

749@register_type( 

750 models.ModuleBayTemplate, 

751 fields='__all__', 

752 filters=ModuleBayTemplateFilter, 

753 pagination=True 

754) 

755class ModuleBayTemplateType(ModularComponentTemplateType): 

756 module_bay_types: list[Annotated["ModuleBayTypeType", strawberry.lazy('dcim.graphql.types')]] 

757 

758 

759@register_type( 

760 models.ModuleBayType, 

761 fields='__all__', 

762 filters=ModuleBayTypeFilter, 

763 pagination=True 

764) 

765class ModuleBayTypeType(PrimaryObjectType): 

766 color: str 

767 manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] | None 

768 module_types: list[Annotated["ModuleTypeType", strawberry.lazy('dcim.graphql.types')]] 

769 module_bays: list[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] 

770 module_bay_templates: list[Annotated["ModuleBayTemplateType", strawberry.lazy('dcim.graphql.types')]] 

771 

772 

773@register_type( 

774 models.ModuleTypeProfile, 

775 fields='__all__', 

776 filters=ModuleTypeProfileFilter, 

777 pagination=True 

778) 

779class ModuleTypeProfileType(PrimaryObjectType): 

780 module_types: list[Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')]] 

781 

782 

783@register_type( 

784 models.ModuleType, 

785 fields='__all__', 

786 filters=ModuleTypeFilter, 

787 pagination=True 

788) 

789class ModuleTypeType(PrimaryObjectType): 

790 module_count: BigInt 

791 console_port_template_count: BigInt 

792 console_server_port_template_count: BigInt 

793 power_port_template_count: BigInt 

794 power_outlet_template_count: BigInt 

795 cooling_intake_template_count: BigInt 

796 cooling_outflow_template_count: BigInt 

797 interface_template_count: BigInt 

798 front_port_template_count: BigInt 

799 rear_port_template_count: BigInt 

800 module_bay_template_count: BigInt 

801 profile: Annotated["ModuleTypeProfileType", strawberry.lazy('dcim.graphql.types')] | None 

802 manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] 

803 module_bay_types: list[Annotated["ModuleBayTypeType", strawberry.lazy('dcim.graphql.types')]] 

804 

805 frontporttemplates: list[Annotated["FrontPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

806 consoleserverporttemplates: list[Annotated["ConsoleServerPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

807 interfacetemplates: list[Annotated["InterfaceTemplateType", strawberry.lazy('dcim.graphql.types')]] 

808 powerporttemplates: list[Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

809 poweroutlettemplates: list[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]] 

810 coolingintaketemplates: list[Annotated["CoolingIntakeTemplateType", strawberry.lazy('dcim.graphql.types')]] 

811 coolingoutflowtemplates: list[Annotated["CoolingOutflowTemplateType", strawberry.lazy('dcim.graphql.types')]] 

812 rearporttemplates: list[Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

813 instances: list[Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')]] 

814 consoleporttemplates: list[Annotated["ConsolePortTemplateType", strawberry.lazy('dcim.graphql.types')]] 

815 

816 

817@register_type( 

818 models.Platform, 

819 exclude=['path', 'sort_path'], 

820 filters=PlatformFilter, 

821 pagination=True 

822) 

823class PlatformType(NestedLtreeGroupObjectType): 

824 parent: Annotated['PlatformType', strawberry.lazy('dcim.graphql.types')] | None 

825 children: list[Annotated['PlatformType', strawberry.lazy('dcim.graphql.types')]] 

826 manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] | None 

827 config_template: Annotated["ConfigTemplateType", strawberry.lazy('extras.graphql.types')] | None 

828 

829 virtual_machines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]] 

830 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

831 

832 

833@register_type( 

834 models.PortMapping, 

835 fields='__all__', 

836 filters=PortMappingFilter, 

837 pagination=True 

838) 

839class PortMappingType(ModularComponentTemplateType): 

840 front_port: Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')] 

841 rear_port: Annotated["RearPortType", strawberry.lazy('dcim.graphql.types')] 

842 

843 

844@register_type( 

845 models.PortTemplateMapping, 

846 fields='__all__', 

847 filters=PortTemplateMappingFilter, 

848 pagination=True 

849) 

850class PortMappingTemplateType(ModularComponentTemplateType): 

851 front_port: Annotated["FrontPortTemplateType", strawberry.lazy('dcim.graphql.types')] 

852 rear_port: Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')] 

853 

854 

855@register_type( 

856 models.PowerFeed, 

857 exclude=['_path'], 

858 filters=PowerFeedFilter, 

859 pagination=True 

860) 

861class PowerFeedType(CabledObjectMixin, PathEndpointMixin, PrimaryObjectType): 

862 power_panel: Annotated["PowerPanelType", strawberry.lazy('dcim.graphql.types')] 

863 rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')] | None 

864 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

865 

866 

867@register_type( 

868 models.PowerOutlet, 

869 exclude=['_path'], 

870 filters=PowerOutletFilter, 

871 pagination=True 

872) 

873class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin): 

874 power_port: Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')] | None 

875 color: str 

876 

877 

878@register_type( 

879 models.PowerOutletTemplate, 

880 fields='__all__', 

881 filters=PowerOutletTemplateFilter, 

882 pagination=True 

883) 

884class PowerOutletTemplateType(ModularComponentTemplateType): 

885 power_port: Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')] | None 

886 color: str 

887 

888 

889@register_type( 

890 models.PowerPanel, 

891 fields='__all__', 

892 filters=PowerPanelFilter, 

893 pagination=True 

894) 

895class PowerPanelType(ContactsMixin, PrimaryObjectType): 

896 site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] 

897 location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None 

898 

899 powerfeeds: list[Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')]] 

900 

901 

902@register_type( 

903 models.PowerPort, 

904 exclude=['_path'], 

905 filters=PowerPortFilter, 

906 pagination=True 

907) 

908class PowerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin): 

909 

910 poweroutlets: list[Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')]] 

911 

912 

913@register_type( 

914 models.PowerPortTemplate, 

915 fields='__all__', 

916 filters=PowerPortTemplateFilter, 

917 pagination=True 

918) 

919class PowerPortTemplateType(ModularComponentTemplateType): 

920 poweroutlet_templates: list[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]] 

921 

922 

923@register_type( 

924 models.CoolingFeed, 

925 exclude=['_abs_max_flow'], 

926 filters=CoolingFeedFilter, 

927 pagination=True 

928) 

929class CoolingFeedType(PrimaryObjectType): 

930 cooling_source: Annotated["CoolingSourceType", strawberry.lazy('dcim.graphql.types')] 

931 rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')] | None 

932 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

933 

934 

935@register_type( 

936 models.CoolingOutflow, 

937 exclude=['_abs_diameter'], 

938 filters=CoolingOutflowFilter, 

939 pagination=True 

940) 

941class CoolingOutflowType(ModularComponentType): 

942 cooling_intake: Annotated["CoolingIntakeType", strawberry.lazy('dcim.graphql.types')] | None 

943 

944 

945@register_type( 

946 models.CoolingOutflowTemplate, 

947 exclude=['_abs_diameter'], 

948 filters=CoolingOutflowTemplateFilter, 

949 pagination=True 

950) 

951class CoolingOutflowTemplateType(ModularComponentTemplateType): 

952 cooling_intake: Annotated["CoolingIntakeTemplateType", strawberry.lazy('dcim.graphql.types')] | None 

953 

954 

955@register_type( 

956 models.CoolingIntake, 

957 exclude=['_abs_diameter', '_abs_max_flow'], 

958 filters=CoolingIntakeFilter, 

959 pagination=True 

960) 

961class CoolingIntakeType(ModularComponentType): 

962 cooling_outflow: Annotated["CoolingOutflowType", strawberry.lazy('dcim.graphql.types')] | None 

963 

964 coolingoutflows: list[Annotated["CoolingOutflowType", strawberry.lazy('dcim.graphql.types')]] 

965 

966 

967@register_type( 

968 models.CoolingIntakeTemplate, 

969 exclude=['_abs_diameter', '_abs_max_flow'], 

970 filters=CoolingIntakeTemplateFilter, 

971 pagination=True 

972) 

973class CoolingIntakeTemplateType(ModularComponentTemplateType): 

974 coolingoutflow_templates: list[Annotated["CoolingOutflowTemplateType", strawberry.lazy('dcim.graphql.types')]] 

975 

976 

977@register_type( 

978 models.CoolingSource, 

979 fields='__all__', 

980 filters=CoolingSourceFilter, 

981 pagination=True 

982) 

983class CoolingSourceType(ContactsMixin, PrimaryObjectType): 

984 site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] 

985 location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None 

986 

987 cooling_feeds: list[Annotated["CoolingFeedType", strawberry.lazy('dcim.graphql.types')]] 

988 

989 

990@register_type( 

991 models.RackGroup, 

992 fields='__all__', 

993 filters=RackGroupFilter, 

994 pagination=True 

995) 

996class RackGroupType(OrganizationalObjectType): 

997 

998 racks: list[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]] 

999 

1000 

1001@register_type( 

1002 models.RackType, 

1003 fields='__all__', 

1004 filters=RackTypeFilter, 

1005 pagination=True 

1006) 

1007class RackTypeType(ImageAttachmentsMixin, PrimaryObjectType): 

1008 rack_count: BigInt 

1009 manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] 

1010 

1011 

1012@register_type( 

1013 models.Rack, 

1014 fields='__all__', 

1015 filters=RackFilter, 

1016 pagination=True 

1017) 

1018class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType): 

1019 site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] 

1020 location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None 

1021 group: Annotated["RackGroupType", strawberry.lazy('dcim.graphql.types')] | None 

1022 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

1023 role: Annotated["RackRoleType", strawberry.lazy('dcim.graphql.types')] | None 

1024 

1025 rack_type: Annotated["RackTypeType", strawberry.lazy('dcim.graphql.types')] | None 

1026 reservations: list[Annotated["RackReservationType", strawberry.lazy('dcim.graphql.types')]] 

1027 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

1028 powerfeeds: list[Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')]] 

1029 cabletermination_set: list[Annotated["CableTerminationType", strawberry.lazy('dcim.graphql.types')]] 

1030 

1031 

1032@register_type( 

1033 models.RackReservation, 

1034 fields='__all__', 

1035 filters=RackReservationFilter, 

1036 pagination=True 

1037) 

1038class RackReservationType(PrimaryObjectType): 

1039 units: list[int] 

1040 rack: Annotated["RackType", strawberry.lazy('dcim.graphql.types')] 

1041 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

1042 user: Annotated["UserType", strawberry.lazy('users.graphql.types')] 

1043 

1044 @classmethod 

1045 def get_queryset(cls, queryset, info, **kwargs): 

1046 queryset = super().get_queryset(queryset, info, **kwargs) 

1047 # Annotate unit_count here so RackReservationFilter.unit_count can reference it. The field below 

1048 # is resolved from `units` rather than from this annotation, which is not applied on every path 

1049 # by which a RackReservation may be resolved. 

1050 return queryset.annotate( 

1051 unit_count=Func('units', function='CARDINALITY', output_field=IntegerField()) 

1052 ) 

1053 

1054 # Ensure `units` is fetched when `unit_count` is requested 

1055 @strawberry_django.field(only=['units']) 

1056 def unit_count(self) -> int: 

1057 return len(self.units) 

1058 

1059 

1060@register_type( 

1061 models.RackRole, 

1062 fields='__all__', 

1063 filters=RackRoleFilter, 

1064 pagination=True 

1065) 

1066class RackRoleType(OrganizationalObjectType): 

1067 color: str 

1068 

1069 racks: list[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]] 

1070 

1071 

1072@register_type( 

1073 models.RearPort, 

1074 fields='__all__', 

1075 filters=RearPortFilter, 

1076 pagination=True 

1077) 

1078class RearPortType(ModularComponentType, CabledObjectMixin): 

1079 color: str 

1080 

1081 mappings: list[Annotated["PortMappingType", strawberry.lazy('dcim.graphql.types')]] 

1082 

1083 

1084@register_type( 

1085 models.RearPortTemplate, 

1086 fields='__all__', 

1087 filters=RearPortTemplateFilter, 

1088 pagination=True 

1089) 

1090class RearPortTemplateType(ModularComponentTemplateType): 

1091 color: str 

1092 

1093 mappings: list[Annotated["PortMappingTemplateType", strawberry.lazy('dcim.graphql.types')]] 

1094 

1095 

1096@register_type( 

1097 models.Region, 

1098 exclude=['parent', 'path', 'sort_path'], 

1099 filters=RegionFilter, 

1100 pagination=True 

1101) 

1102class RegionType(VLANGroupsMixin, ContactsMixin, NestedLtreeGroupObjectType): 

1103 

1104 sites: list[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]] 

1105 children: list[Annotated["RegionType", strawberry.lazy('dcim.graphql.types')]] 

1106 

1107 @strawberry_django.field(prefetch_related='parent', only=['parent_id']) 

1108 def parent(self) -> Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None: 

1109 return self.parent 

1110 

1111 @strawberry_django.field( 

1112 prefetch_related=lambda info: RestrictedPrefetch( 

1113 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() 

1114 ), 

1115 ) 

1116 def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: 

1117 return self.cluster_set.all() 

1118 

1119 @strawberry_django.field( 

1120 prefetch_related=lambda info: RestrictedPrefetch( 

1121 'circuit_terminations', info.context.request.user, 'view', 

1122 queryset=CircuitTermination.objects.all() 

1123 ), 

1124 ) 

1125 def circuit_terminations(self) -> list[ 

1126 Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] 

1127 ]: 

1128 return self.circuit_terminations.all() 

1129 

1130 

1131@register_type( 

1132 models.Site, 

1133 fields='__all__', 

1134 filters=SiteFilter, 

1135 pagination=True 

1136) 

1137class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObjectType): 

1138 time_zone: str | None 

1139 region: Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None 

1140 group: Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None 

1141 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

1142 

1143 prefixes: list[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]] 

1144 virtual_machines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]] 

1145 racks: list[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]] 

1146 cabletermination_set: list[Annotated["CableTerminationType", strawberry.lazy('dcim.graphql.types')]] 

1147 powerpanel_set: list[Annotated["PowerPanelType", strawberry.lazy('dcim.graphql.types')]] 

1148 devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

1149 locations: list[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]] 

1150 asns: list[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]] 

1151 vlans: list[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]] 

1152 

1153 @strawberry_django.field( 

1154 prefetch_related=lambda info: RestrictedPrefetch( 

1155 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() 

1156 ), 

1157 ) 

1158 def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: 

1159 return self.cluster_set.all() 

1160 

1161 @strawberry_django.field( 

1162 prefetch_related=lambda info: RestrictedPrefetch( 

1163 'circuit_terminations', info.context.request.user, 'view', 

1164 queryset=CircuitTermination.objects.all() 

1165 ), 

1166 ) 

1167 def circuit_terminations(self) -> list[ 

1168 Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] 

1169 ]: 

1170 return self.circuit_terminations.all() 

1171 

1172 

1173@register_type( 

1174 models.SiteGroup, 

1175 exclude=['parent', 'path', 'sort_path'], # bug - temp 

1176 filters=SiteGroupFilter, 

1177 pagination=True 

1178) 

1179class SiteGroupType(VLANGroupsMixin, ContactsMixin, NestedLtreeGroupObjectType): 

1180 

1181 sites: list[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]] 

1182 children: list[Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')]] 

1183 

1184 @strawberry_django.field(prefetch_related='parent', only=['parent_id']) 

1185 def parent(self) -> Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None: 

1186 return self.parent 

1187 

1188 @strawberry_django.field( 

1189 prefetch_related=lambda info: RestrictedPrefetch( 

1190 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() 

1191 ), 

1192 ) 

1193 def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: 

1194 return self.cluster_set.all() 

1195 

1196 @strawberry_django.field( 

1197 prefetch_related=lambda info: RestrictedPrefetch( 

1198 'circuit_terminations', info.context.request.user, 'view', 

1199 queryset=CircuitTermination.objects.all() 

1200 ), 

1201 ) 

1202 def circuit_terminations(self) -> list[ 

1203 Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] 

1204 ]: 

1205 return self.circuit_terminations.all() 

1206 

1207 

1208@register_type( 

1209 models.VirtualChassis, 

1210 fields='__all__', 

1211 filters=VirtualChassisFilter, 

1212 pagination=True 

1213) 

1214class VirtualChassisType(PrimaryObjectType): 

1215 member_count: BigInt 

1216 master: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None 

1217 

1218 members: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] 

1219 

1220 

1221@register_type( 

1222 models.VirtualDeviceContext, 

1223 fields='__all__', 

1224 filters=VirtualDeviceContextFilter, 

1225 pagination=True 

1226) 

1227class VirtualDeviceContextType(PrimaryObjectType): 

1228 device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None 

1229 primary_ip4: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None 

1230 primary_ip6: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None 

1231 tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None 

1232 

1233 interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]