filtersets.py 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047
  1. import django_filters
  2. from django.contrib.auth import get_user_model
  3. from django.utils.translation import gettext as _
  4. from extras.filtersets import LocalConfigContextFilterSet
  5. from extras.models import ConfigTemplate
  6. from ipam.filtersets import PrimaryIPFilterSet
  7. from ipam.models import ASN, IPAddress, VRF
  8. from netbox.filtersets import (
  9. BaseFilterSet, ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet,
  10. )
  11. from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
  12. from tenancy.models import *
  13. from utilities.choices import ColorChoices
  14. from utilities.filters import (
  15. ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
  16. TreeNodeMultipleChoiceFilter,
  17. )
  18. from virtualization.models import Cluster
  19. from vpn.models import L2VPN
  20. from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
  21. from .choices import *
  22. from .constants import *
  23. from .models import *
  24. __all__ = (
  25. 'CableFilterSet',
  26. 'CabledObjectFilterSet',
  27. 'CableTerminationFilterSet',
  28. 'CommonInterfaceFilterSet',
  29. 'ConsoleConnectionFilterSet',
  30. 'ConsolePortFilterSet',
  31. 'ConsolePortTemplateFilterSet',
  32. 'ConsoleServerPortFilterSet',
  33. 'ConsoleServerPortTemplateFilterSet',
  34. 'DeviceBayFilterSet',
  35. 'DeviceBayTemplateFilterSet',
  36. 'DeviceFilterSet',
  37. 'DeviceRoleFilterSet',
  38. 'DeviceTypeFilterSet',
  39. 'FrontPortFilterSet',
  40. 'FrontPortTemplateFilterSet',
  41. 'InterfaceConnectionFilterSet',
  42. 'InterfaceFilterSet',
  43. 'InterfaceTemplateFilterSet',
  44. 'InventoryItemFilterSet',
  45. 'InventoryItemRoleFilterSet',
  46. 'InventoryItemTemplateFilterSet',
  47. 'LocationFilterSet',
  48. 'ManufacturerFilterSet',
  49. 'ModuleBayFilterSet',
  50. 'ModuleBayTemplateFilterSet',
  51. 'ModuleFilterSet',
  52. 'ModuleTypeFilterSet',
  53. 'PathEndpointFilterSet',
  54. 'PlatformFilterSet',
  55. 'PowerConnectionFilterSet',
  56. 'PowerFeedFilterSet',
  57. 'PowerOutletFilterSet',
  58. 'PowerOutletTemplateFilterSet',
  59. 'PowerPanelFilterSet',
  60. 'PowerPortFilterSet',
  61. 'PowerPortTemplateFilterSet',
  62. 'RackFilterSet',
  63. 'RackReservationFilterSet',
  64. 'RackRoleFilterSet',
  65. 'RearPortFilterSet',
  66. 'RearPortTemplateFilterSet',
  67. 'RegionFilterSet',
  68. 'SiteFilterSet',
  69. 'SiteGroupFilterSet',
  70. 'VirtualChassisFilterSet',
  71. 'VirtualDeviceContextFilterSet',
  72. )
  73. class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  74. parent_id = django_filters.ModelMultipleChoiceFilter(
  75. queryset=Region.objects.all(),
  76. label=_('Parent region (ID)'),
  77. )
  78. parent = django_filters.ModelMultipleChoiceFilter(
  79. field_name='parent__slug',
  80. queryset=Region.objects.all(),
  81. to_field_name='slug',
  82. label=_('Parent region (slug)'),
  83. )
  84. class Meta:
  85. model = Region
  86. fields = ['id', 'name', 'slug', 'description']
  87. class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  88. parent_id = django_filters.ModelMultipleChoiceFilter(
  89. queryset=SiteGroup.objects.all(),
  90. label=_('Parent site group (ID)'),
  91. )
  92. parent = django_filters.ModelMultipleChoiceFilter(
  93. field_name='parent__slug',
  94. queryset=SiteGroup.objects.all(),
  95. to_field_name='slug',
  96. label=_('Parent site group (slug)'),
  97. )
  98. class Meta:
  99. model = SiteGroup
  100. fields = ['id', 'name', 'slug', 'description']
  101. class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  102. status = django_filters.MultipleChoiceFilter(
  103. choices=SiteStatusChoices,
  104. null_value=None
  105. )
  106. region_id = TreeNodeMultipleChoiceFilter(
  107. queryset=Region.objects.all(),
  108. field_name='region',
  109. lookup_expr='in',
  110. label=_('Region (ID)'),
  111. )
  112. region = TreeNodeMultipleChoiceFilter(
  113. queryset=Region.objects.all(),
  114. lookup_expr='in',
  115. to_field_name='slug',
  116. label=_('Region (slug)'),
  117. )
  118. group_id = TreeNodeMultipleChoiceFilter(
  119. queryset=SiteGroup.objects.all(),
  120. field_name='group',
  121. lookup_expr='in',
  122. label=_('Group (ID)'),
  123. )
  124. group = TreeNodeMultipleChoiceFilter(
  125. queryset=SiteGroup.objects.all(),
  126. lookup_expr='in',
  127. to_field_name='slug',
  128. label=_('Group (slug)'),
  129. )
  130. asn = django_filters.ModelMultipleChoiceFilter(
  131. field_name='asns__asn',
  132. queryset=ASN.objects.all(),
  133. to_field_name='asn',
  134. label=_('AS (ID)'),
  135. )
  136. asn_id = django_filters.ModelMultipleChoiceFilter(
  137. field_name='asns',
  138. queryset=ASN.objects.all(),
  139. label=_('AS (ID)'),
  140. )
  141. class Meta:
  142. model = Site
  143. fields = (
  144. 'id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description'
  145. )
  146. def search(self, queryset, name, value):
  147. if not value.strip():
  148. return queryset
  149. qs_filter = (
  150. Q(name__icontains=value) |
  151. Q(facility__icontains=value) |
  152. Q(description__icontains=value) |
  153. Q(physical_address__icontains=value) |
  154. Q(shipping_address__icontains=value) |
  155. Q(comments__icontains=value)
  156. )
  157. try:
  158. qs_filter |= Q(asns__asn=int(value.strip()))
  159. except ValueError:
  160. pass
  161. return queryset.filter(qs_filter).distinct()
  162. class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalModelFilterSet):
  163. region_id = TreeNodeMultipleChoiceFilter(
  164. queryset=Region.objects.all(),
  165. field_name='site__region',
  166. lookup_expr='in',
  167. label=_('Region (ID)'),
  168. )
  169. region = TreeNodeMultipleChoiceFilter(
  170. queryset=Region.objects.all(),
  171. field_name='site__region',
  172. lookup_expr='in',
  173. to_field_name='slug',
  174. label=_('Region (slug)'),
  175. )
  176. site_group_id = TreeNodeMultipleChoiceFilter(
  177. queryset=SiteGroup.objects.all(),
  178. field_name='site__group',
  179. lookup_expr='in',
  180. label=_('Site group (ID)'),
  181. )
  182. site_group = TreeNodeMultipleChoiceFilter(
  183. queryset=SiteGroup.objects.all(),
  184. field_name='site__group',
  185. lookup_expr='in',
  186. to_field_name='slug',
  187. label=_('Site group (slug)'),
  188. )
  189. site_id = django_filters.ModelMultipleChoiceFilter(
  190. queryset=Site.objects.all(),
  191. label=_('Site (ID)'),
  192. )
  193. site = django_filters.ModelMultipleChoiceFilter(
  194. field_name='site__slug',
  195. queryset=Site.objects.all(),
  196. to_field_name='slug',
  197. label=_('Site (slug)'),
  198. )
  199. parent_id = TreeNodeMultipleChoiceFilter(
  200. queryset=Location.objects.all(),
  201. field_name='parent',
  202. lookup_expr='in',
  203. label=_('Location (ID)'),
  204. )
  205. parent = TreeNodeMultipleChoiceFilter(
  206. queryset=Location.objects.all(),
  207. field_name='parent',
  208. lookup_expr='in',
  209. to_field_name='slug',
  210. label=_('Location (slug)'),
  211. )
  212. status = django_filters.MultipleChoiceFilter(
  213. choices=LocationStatusChoices,
  214. null_value=None
  215. )
  216. class Meta:
  217. model = Location
  218. fields = ['id', 'name', 'slug', 'status', 'description']
  219. def search(self, queryset, name, value):
  220. if not value.strip():
  221. return queryset
  222. return queryset.filter(
  223. Q(name__icontains=value) |
  224. Q(description__icontains=value)
  225. )
  226. class RackRoleFilterSet(OrganizationalModelFilterSet):
  227. class Meta:
  228. model = RackRole
  229. fields = ['id', 'name', 'slug', 'color', 'description']
  230. class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  231. region_id = TreeNodeMultipleChoiceFilter(
  232. queryset=Region.objects.all(),
  233. field_name='site__region',
  234. lookup_expr='in',
  235. label=_('Region (ID)'),
  236. )
  237. region = TreeNodeMultipleChoiceFilter(
  238. queryset=Region.objects.all(),
  239. field_name='site__region',
  240. lookup_expr='in',
  241. to_field_name='slug',
  242. label=_('Region (slug)'),
  243. )
  244. site_group_id = TreeNodeMultipleChoiceFilter(
  245. queryset=SiteGroup.objects.all(),
  246. field_name='site__group',
  247. lookup_expr='in',
  248. label=_('Site group (ID)'),
  249. )
  250. site_group = TreeNodeMultipleChoiceFilter(
  251. queryset=SiteGroup.objects.all(),
  252. field_name='site__group',
  253. lookup_expr='in',
  254. to_field_name='slug',
  255. label=_('Site group (slug)'),
  256. )
  257. site_id = django_filters.ModelMultipleChoiceFilter(
  258. queryset=Site.objects.all(),
  259. label=_('Site (ID)'),
  260. )
  261. site = django_filters.ModelMultipleChoiceFilter(
  262. field_name='site__slug',
  263. queryset=Site.objects.all(),
  264. to_field_name='slug',
  265. label=_('Site (slug)'),
  266. )
  267. location_id = TreeNodeMultipleChoiceFilter(
  268. queryset=Location.objects.all(),
  269. field_name='location',
  270. lookup_expr='in',
  271. label=_('Location (ID)'),
  272. )
  273. location = TreeNodeMultipleChoiceFilter(
  274. queryset=Location.objects.all(),
  275. field_name='location',
  276. lookup_expr='in',
  277. to_field_name='slug',
  278. label=_('Location (slug)'),
  279. )
  280. status = django_filters.MultipleChoiceFilter(
  281. choices=RackStatusChoices,
  282. null_value=None
  283. )
  284. type = django_filters.MultipleChoiceFilter(
  285. choices=RackTypeChoices
  286. )
  287. width = django_filters.MultipleChoiceFilter(
  288. choices=RackWidthChoices
  289. )
  290. role_id = django_filters.ModelMultipleChoiceFilter(
  291. queryset=RackRole.objects.all(),
  292. label=_('Role (ID)'),
  293. )
  294. role = django_filters.ModelMultipleChoiceFilter(
  295. field_name='role__slug',
  296. queryset=RackRole.objects.all(),
  297. to_field_name='slug',
  298. label=_('Role (slug)'),
  299. )
  300. serial = MultiValueCharFilter(
  301. lookup_expr='iexact'
  302. )
  303. class Meta:
  304. model = Rack
  305. fields = [
  306. 'id', 'name', 'facility_id', 'asset_tag', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
  307. 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description',
  308. ]
  309. def search(self, queryset, name, value):
  310. if not value.strip():
  311. return queryset
  312. return queryset.filter(
  313. Q(name__icontains=value) |
  314. Q(facility_id__icontains=value) |
  315. Q(serial__icontains=value.strip()) |
  316. Q(asset_tag__icontains=value.strip()) |
  317. Q(description__icontains=value) |
  318. Q(comments__icontains=value)
  319. )
  320. class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  321. rack_id = django_filters.ModelMultipleChoiceFilter(
  322. queryset=Rack.objects.all(),
  323. label=_('Rack (ID)'),
  324. )
  325. site_id = django_filters.ModelMultipleChoiceFilter(
  326. field_name='rack__site',
  327. queryset=Site.objects.all(),
  328. label=_('Site (ID)'),
  329. )
  330. site = django_filters.ModelMultipleChoiceFilter(
  331. field_name='rack__site__slug',
  332. queryset=Site.objects.all(),
  333. to_field_name='slug',
  334. label=_('Site (slug)'),
  335. )
  336. region_id = TreeNodeMultipleChoiceFilter(
  337. queryset=Region.objects.all(),
  338. field_name='rack__site__region',
  339. lookup_expr='in',
  340. label=_('Region (ID)'),
  341. )
  342. region = TreeNodeMultipleChoiceFilter(
  343. queryset=Region.objects.all(),
  344. field_name='rack__site__region',
  345. lookup_expr='in',
  346. to_field_name='slug',
  347. label=_('Region (slug)'),
  348. )
  349. site_group_id = TreeNodeMultipleChoiceFilter(
  350. queryset=SiteGroup.objects.all(),
  351. field_name='rack__site__group',
  352. lookup_expr='in',
  353. label=_('Site group (ID)'),
  354. )
  355. site_group = TreeNodeMultipleChoiceFilter(
  356. queryset=SiteGroup.objects.all(),
  357. field_name='rack__site__group',
  358. lookup_expr='in',
  359. to_field_name='slug',
  360. label=_('Site group (slug)'),
  361. )
  362. location_id = TreeNodeMultipleChoiceFilter(
  363. queryset=Location.objects.all(),
  364. field_name='rack__location',
  365. lookup_expr='in',
  366. label=_('Location (ID)'),
  367. )
  368. location = TreeNodeMultipleChoiceFilter(
  369. queryset=Location.objects.all(),
  370. field_name='rack__location',
  371. lookup_expr='in',
  372. to_field_name='slug',
  373. label=_('Location (slug)'),
  374. )
  375. user_id = django_filters.ModelMultipleChoiceFilter(
  376. queryset=get_user_model().objects.all(),
  377. label=_('User (ID)'),
  378. )
  379. user = django_filters.ModelMultipleChoiceFilter(
  380. field_name='user__username',
  381. queryset=get_user_model().objects.all(),
  382. to_field_name='username',
  383. label=_('User (name)'),
  384. )
  385. class Meta:
  386. model = RackReservation
  387. fields = ['id', 'created', 'description']
  388. def search(self, queryset, name, value):
  389. if not value.strip():
  390. return queryset
  391. return queryset.filter(
  392. Q(rack__name__icontains=value) |
  393. Q(rack__facility_id__icontains=value) |
  394. Q(user__username__icontains=value) |
  395. Q(description__icontains=value)
  396. )
  397. class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  398. class Meta:
  399. model = Manufacturer
  400. fields = ['id', 'name', 'slug', 'description']
  401. class DeviceTypeFilterSet(NetBoxModelFilterSet):
  402. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  403. queryset=Manufacturer.objects.all(),
  404. label=_('Manufacturer (ID)'),
  405. )
  406. manufacturer = django_filters.ModelMultipleChoiceFilter(
  407. field_name='manufacturer__slug',
  408. queryset=Manufacturer.objects.all(),
  409. to_field_name='slug',
  410. label=_('Manufacturer (slug)'),
  411. )
  412. default_platform_id = django_filters.ModelMultipleChoiceFilter(
  413. queryset=Platform.objects.all(),
  414. label=_('Default platform (ID)'),
  415. )
  416. default_platform = django_filters.ModelMultipleChoiceFilter(
  417. field_name='default_platform__slug',
  418. queryset=Platform.objects.all(),
  419. to_field_name='slug',
  420. label=_('Default platform (slug)'),
  421. )
  422. has_front_image = django_filters.BooleanFilter(
  423. label=_('Has a front image'),
  424. method='_has_front_image'
  425. )
  426. has_rear_image = django_filters.BooleanFilter(
  427. label=_('Has a rear image'),
  428. method='_has_rear_image'
  429. )
  430. console_ports = django_filters.BooleanFilter(
  431. method='_console_ports',
  432. label=_('Has console ports'),
  433. )
  434. console_server_ports = django_filters.BooleanFilter(
  435. method='_console_server_ports',
  436. label=_('Has console server ports'),
  437. )
  438. power_ports = django_filters.BooleanFilter(
  439. method='_power_ports',
  440. label=_('Has power ports'),
  441. )
  442. power_outlets = django_filters.BooleanFilter(
  443. method='_power_outlets',
  444. label=_('Has power outlets'),
  445. )
  446. interfaces = django_filters.BooleanFilter(
  447. method='_interfaces',
  448. label=_('Has interfaces'),
  449. )
  450. pass_through_ports = django_filters.BooleanFilter(
  451. method='_pass_through_ports',
  452. label=_('Has pass-through ports'),
  453. )
  454. module_bays = django_filters.BooleanFilter(
  455. method='_module_bays',
  456. label=_('Has module bays'),
  457. )
  458. device_bays = django_filters.BooleanFilter(
  459. method='_device_bays',
  460. label=_('Has device bays'),
  461. )
  462. inventory_items = django_filters.BooleanFilter(
  463. method='_inventory_items',
  464. label=_('Has inventory items'),
  465. )
  466. class Meta:
  467. model = DeviceType
  468. fields = [
  469. 'id', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization', 'is_full_depth',
  470. 'subdevice_role', 'airflow', 'weight', 'weight_unit', 'description',
  471. ]
  472. def search(self, queryset, name, value):
  473. if not value.strip():
  474. return queryset
  475. return queryset.filter(
  476. Q(manufacturer__name__icontains=value) |
  477. Q(model__icontains=value) |
  478. Q(part_number__icontains=value) |
  479. Q(description__icontains=value) |
  480. Q(comments__icontains=value)
  481. )
  482. def _has_front_image(self, queryset, name, value):
  483. if value:
  484. return queryset.exclude(front_image='')
  485. else:
  486. return queryset.filter(front_image='')
  487. def _has_rear_image(self, queryset, name, value):
  488. if value:
  489. return queryset.exclude(rear_image='')
  490. else:
  491. return queryset.filter(rear_image='')
  492. def _console_ports(self, queryset, name, value):
  493. return queryset.exclude(consoleporttemplates__isnull=value)
  494. def _console_server_ports(self, queryset, name, value):
  495. return queryset.exclude(consoleserverporttemplates__isnull=value)
  496. def _power_ports(self, queryset, name, value):
  497. return queryset.exclude(powerporttemplates__isnull=value)
  498. def _power_outlets(self, queryset, name, value):
  499. return queryset.exclude(poweroutlettemplates__isnull=value)
  500. def _interfaces(self, queryset, name, value):
  501. return queryset.exclude(interfacetemplates__isnull=value)
  502. def _pass_through_ports(self, queryset, name, value):
  503. return queryset.exclude(
  504. frontporttemplates__isnull=value,
  505. rearporttemplates__isnull=value
  506. )
  507. def _module_bays(self, queryset, name, value):
  508. return queryset.exclude(modulebaytemplates__isnull=value)
  509. def _device_bays(self, queryset, name, value):
  510. return queryset.exclude(devicebaytemplates__isnull=value)
  511. def _inventory_items(self, queryset, name, value):
  512. return queryset.exclude(inventoryitemtemplates__isnull=value)
  513. class ModuleTypeFilterSet(NetBoxModelFilterSet):
  514. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  515. queryset=Manufacturer.objects.all(),
  516. label=_('Manufacturer (ID)'),
  517. )
  518. manufacturer = django_filters.ModelMultipleChoiceFilter(
  519. field_name='manufacturer__slug',
  520. queryset=Manufacturer.objects.all(),
  521. to_field_name='slug',
  522. label=_('Manufacturer (slug)'),
  523. )
  524. console_ports = django_filters.BooleanFilter(
  525. method='_console_ports',
  526. label=_('Has console ports'),
  527. )
  528. console_server_ports = django_filters.BooleanFilter(
  529. method='_console_server_ports',
  530. label=_('Has console server ports'),
  531. )
  532. power_ports = django_filters.BooleanFilter(
  533. method='_power_ports',
  534. label=_('Has power ports'),
  535. )
  536. power_outlets = django_filters.BooleanFilter(
  537. method='_power_outlets',
  538. label=_('Has power outlets'),
  539. )
  540. interfaces = django_filters.BooleanFilter(
  541. method='_interfaces',
  542. label=_('Has interfaces'),
  543. )
  544. pass_through_ports = django_filters.BooleanFilter(
  545. method='_pass_through_ports',
  546. label=_('Has pass-through ports'),
  547. )
  548. class Meta:
  549. model = ModuleType
  550. fields = ['id', 'model', 'part_number', 'weight', 'weight_unit', 'description']
  551. def search(self, queryset, name, value):
  552. if not value.strip():
  553. return queryset
  554. return queryset.filter(
  555. Q(manufacturer__name__icontains=value) |
  556. Q(model__icontains=value) |
  557. Q(part_number__icontains=value) |
  558. Q(description__icontains=value) |
  559. Q(comments__icontains=value)
  560. )
  561. def _console_ports(self, queryset, name, value):
  562. return queryset.exclude(consoleporttemplates__isnull=value)
  563. def _console_server_ports(self, queryset, name, value):
  564. return queryset.exclude(consoleserverporttemplates__isnull=value)
  565. def _power_ports(self, queryset, name, value):
  566. return queryset.exclude(powerporttemplates__isnull=value)
  567. def _power_outlets(self, queryset, name, value):
  568. return queryset.exclude(poweroutlettemplates__isnull=value)
  569. def _interfaces(self, queryset, name, value):
  570. return queryset.exclude(interfacetemplates__isnull=value)
  571. def _pass_through_ports(self, queryset, name, value):
  572. return queryset.exclude(
  573. frontporttemplates__isnull=value,
  574. rearporttemplates__isnull=value
  575. )
  576. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  577. q = django_filters.CharFilter(
  578. method='search',
  579. label=_('Search'),
  580. )
  581. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  582. queryset=DeviceType.objects.all(),
  583. field_name='device_type_id',
  584. label=_('Device type (ID)'),
  585. )
  586. def search(self, queryset, name, value):
  587. if not value.strip():
  588. return queryset
  589. return queryset.filter(
  590. Q(name__icontains=value) |
  591. Q(description__icontains=value)
  592. )
  593. class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
  594. moduletype_id = django_filters.ModelMultipleChoiceFilter(
  595. queryset=ModuleType.objects.all(),
  596. field_name='module_type_id',
  597. label=_('Module type (ID)'),
  598. )
  599. class ConsolePortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  600. class Meta:
  601. model = ConsolePortTemplate
  602. fields = ['id', 'name', 'type', 'description']
  603. class ConsoleServerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  604. class Meta:
  605. model = ConsoleServerPortTemplate
  606. fields = ['id', 'name', 'type', 'description']
  607. class PowerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  608. class Meta:
  609. model = PowerPortTemplate
  610. fields = ['id', 'name', 'type', 'maximum_draw', 'allocated_draw', 'description']
  611. class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  612. feed_leg = django_filters.MultipleChoiceFilter(
  613. choices=PowerOutletFeedLegChoices,
  614. null_value=None
  615. )
  616. class Meta:
  617. model = PowerOutletTemplate
  618. fields = ['id', 'name', 'type', 'feed_leg', 'description']
  619. class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  620. type = django_filters.MultipleChoiceFilter(
  621. choices=InterfaceTypeChoices,
  622. null_value=None
  623. )
  624. bridge_id = django_filters.ModelMultipleChoiceFilter(
  625. field_name='bridge',
  626. queryset=InterfaceTemplate.objects.all()
  627. )
  628. poe_mode = django_filters.MultipleChoiceFilter(
  629. choices=InterfacePoEModeChoices
  630. )
  631. poe_type = django_filters.MultipleChoiceFilter(
  632. choices=InterfacePoETypeChoices
  633. )
  634. rf_role = django_filters.MultipleChoiceFilter(
  635. choices=WirelessRoleChoices
  636. )
  637. class Meta:
  638. model = InterfaceTemplate
  639. fields = ['id', 'name', 'type', 'enabled', 'mgmt_only', 'description']
  640. class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  641. type = django_filters.MultipleChoiceFilter(
  642. choices=PortTypeChoices,
  643. null_value=None
  644. )
  645. class Meta:
  646. model = FrontPortTemplate
  647. fields = ['id', 'name', 'type', 'color', 'description']
  648. class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  649. type = django_filters.MultipleChoiceFilter(
  650. choices=PortTypeChoices,
  651. null_value=None
  652. )
  653. class Meta:
  654. model = RearPortTemplate
  655. fields = ['id', 'name', 'type', 'color', 'positions', 'description']
  656. class ModuleBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  657. class Meta:
  658. model = ModuleBayTemplate
  659. fields = ['id', 'name', 'description']
  660. class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  661. class Meta:
  662. model = DeviceBayTemplate
  663. fields = ['id', 'name', 'description']
  664. class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  665. parent_id = django_filters.ModelMultipleChoiceFilter(
  666. queryset=InventoryItemTemplate.objects.all(),
  667. label=_('Parent inventory item (ID)'),
  668. )
  669. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  670. queryset=Manufacturer.objects.all(),
  671. label=_('Manufacturer (ID)'),
  672. )
  673. manufacturer = django_filters.ModelMultipleChoiceFilter(
  674. field_name='manufacturer__slug',
  675. queryset=Manufacturer.objects.all(),
  676. to_field_name='slug',
  677. label=_('Manufacturer (slug)'),
  678. )
  679. role_id = django_filters.ModelMultipleChoiceFilter(
  680. queryset=InventoryItemRole.objects.all(),
  681. label=_('Role (ID)'),
  682. )
  683. role = django_filters.ModelMultipleChoiceFilter(
  684. field_name='role__slug',
  685. queryset=InventoryItemRole.objects.all(),
  686. to_field_name='slug',
  687. label=_('Role (slug)'),
  688. )
  689. component_type = ContentTypeFilter()
  690. component_id = MultiValueNumberFilter()
  691. class Meta:
  692. model = InventoryItemTemplate
  693. fields = ['id', 'name', 'label', 'part_id', 'description']
  694. def search(self, queryset, name, value):
  695. if not value.strip():
  696. return queryset
  697. qs_filter = (
  698. Q(name__icontains=value) |
  699. Q(part_id__icontains=value) |
  700. Q(description__icontains=value)
  701. )
  702. return queryset.filter(qs_filter)
  703. class DeviceRoleFilterSet(OrganizationalModelFilterSet):
  704. config_template_id = django_filters.ModelMultipleChoiceFilter(
  705. queryset=ConfigTemplate.objects.all(),
  706. label=_('Config template (ID)'),
  707. )
  708. class Meta:
  709. model = DeviceRole
  710. fields = ['id', 'name', 'slug', 'color', 'vm_role', 'description']
  711. class PlatformFilterSet(OrganizationalModelFilterSet):
  712. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  713. field_name='manufacturer',
  714. queryset=Manufacturer.objects.all(),
  715. label=_('Manufacturer (ID)'),
  716. )
  717. manufacturer = django_filters.ModelMultipleChoiceFilter(
  718. field_name='manufacturer__slug',
  719. queryset=Manufacturer.objects.all(),
  720. to_field_name='slug',
  721. label=_('Manufacturer (slug)'),
  722. )
  723. config_template_id = django_filters.ModelMultipleChoiceFilter(
  724. queryset=ConfigTemplate.objects.all(),
  725. label=_('Config template (ID)'),
  726. )
  727. class Meta:
  728. model = Platform
  729. fields = ['id', 'name', 'slug', 'description']
  730. class DeviceFilterSet(
  731. NetBoxModelFilterSet,
  732. TenancyFilterSet,
  733. ContactModelFilterSet,
  734. LocalConfigContextFilterSet,
  735. PrimaryIPFilterSet,
  736. ):
  737. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  738. field_name='device_type__manufacturer',
  739. queryset=Manufacturer.objects.all(),
  740. label=_('Manufacturer (ID)'),
  741. )
  742. manufacturer = django_filters.ModelMultipleChoiceFilter(
  743. field_name='device_type__manufacturer__slug',
  744. queryset=Manufacturer.objects.all(),
  745. to_field_name='slug',
  746. label=_('Manufacturer (slug)'),
  747. )
  748. device_type = django_filters.ModelMultipleChoiceFilter(
  749. field_name='device_type__slug',
  750. queryset=DeviceType.objects.all(),
  751. to_field_name='slug',
  752. label=_('Device type (slug)'),
  753. )
  754. device_type_id = django_filters.ModelMultipleChoiceFilter(
  755. queryset=DeviceType.objects.all(),
  756. label=_('Device type (ID)'),
  757. )
  758. role_id = django_filters.ModelMultipleChoiceFilter(
  759. field_name='role_id',
  760. queryset=DeviceRole.objects.all(),
  761. label=_('Role (ID)'),
  762. )
  763. role = django_filters.ModelMultipleChoiceFilter(
  764. field_name='role__slug',
  765. queryset=DeviceRole.objects.all(),
  766. to_field_name='slug',
  767. label=_('Role (slug)'),
  768. )
  769. parent_device_id = django_filters.ModelMultipleChoiceFilter(
  770. field_name='parent_bay__device',
  771. queryset=Device.objects.all(),
  772. label=_('Parent Device (ID)'),
  773. )
  774. platform_id = django_filters.ModelMultipleChoiceFilter(
  775. queryset=Platform.objects.all(),
  776. label=_('Platform (ID)'),
  777. )
  778. platform = django_filters.ModelMultipleChoiceFilter(
  779. field_name='platform__slug',
  780. queryset=Platform.objects.all(),
  781. to_field_name='slug',
  782. label=_('Platform (slug)'),
  783. )
  784. region_id = TreeNodeMultipleChoiceFilter(
  785. queryset=Region.objects.all(),
  786. field_name='site__region',
  787. lookup_expr='in',
  788. label=_('Region (ID)'),
  789. )
  790. region = TreeNodeMultipleChoiceFilter(
  791. queryset=Region.objects.all(),
  792. field_name='site__region',
  793. lookup_expr='in',
  794. to_field_name='slug',
  795. label=_('Region (slug)'),
  796. )
  797. site_group_id = TreeNodeMultipleChoiceFilter(
  798. queryset=SiteGroup.objects.all(),
  799. field_name='site__group',
  800. lookup_expr='in',
  801. label=_('Site group (ID)'),
  802. )
  803. site_group = TreeNodeMultipleChoiceFilter(
  804. queryset=SiteGroup.objects.all(),
  805. field_name='site__group',
  806. lookup_expr='in',
  807. to_field_name='slug',
  808. label=_('Site group (slug)'),
  809. )
  810. site_id = django_filters.ModelMultipleChoiceFilter(
  811. queryset=Site.objects.all(),
  812. label=_('Site (ID)'),
  813. )
  814. site = django_filters.ModelMultipleChoiceFilter(
  815. field_name='site__slug',
  816. queryset=Site.objects.all(),
  817. to_field_name='slug',
  818. label=_('Site name (slug)'),
  819. )
  820. location_id = TreeNodeMultipleChoiceFilter(
  821. queryset=Location.objects.all(),
  822. field_name='location',
  823. lookup_expr='in',
  824. label=_('Location (ID)'),
  825. )
  826. rack_id = django_filters.ModelMultipleChoiceFilter(
  827. field_name='rack',
  828. queryset=Rack.objects.all(),
  829. label=_('Rack (ID)'),
  830. )
  831. cluster_id = django_filters.ModelMultipleChoiceFilter(
  832. queryset=Cluster.objects.all(),
  833. label=_('VM cluster (ID)'),
  834. )
  835. model = django_filters.ModelMultipleChoiceFilter(
  836. field_name='device_type__slug',
  837. queryset=DeviceType.objects.all(),
  838. to_field_name='slug',
  839. label=_('Device model (slug)'),
  840. )
  841. name = MultiValueCharFilter(
  842. lookup_expr='iexact'
  843. )
  844. status = django_filters.MultipleChoiceFilter(
  845. choices=DeviceStatusChoices,
  846. null_value=None
  847. )
  848. is_full_depth = django_filters.BooleanFilter(
  849. field_name='device_type__is_full_depth',
  850. label=_('Is full depth'),
  851. )
  852. mac_address = MultiValueMACAddressFilter(
  853. field_name='interfaces__mac_address',
  854. label=_('MAC address'),
  855. )
  856. serial = MultiValueCharFilter(
  857. lookup_expr='iexact'
  858. )
  859. has_primary_ip = django_filters.BooleanFilter(
  860. method='_has_primary_ip',
  861. label=_('Has a primary IP'),
  862. )
  863. has_oob_ip = django_filters.BooleanFilter(
  864. method='_has_oob_ip',
  865. label=_('Has an out-of-band IP'),
  866. )
  867. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  868. field_name='virtual_chassis',
  869. queryset=VirtualChassis.objects.all(),
  870. label=_('Virtual chassis (ID)'),
  871. )
  872. virtual_chassis_member = django_filters.BooleanFilter(
  873. method='_virtual_chassis_member',
  874. label=_('Is a virtual chassis member')
  875. )
  876. config_template_id = django_filters.ModelMultipleChoiceFilter(
  877. queryset=ConfigTemplate.objects.all(),
  878. label=_('Config template (ID)'),
  879. )
  880. console_ports = django_filters.BooleanFilter(
  881. method='_console_ports',
  882. label=_('Has console ports'),
  883. )
  884. console_server_ports = django_filters.BooleanFilter(
  885. method='_console_server_ports',
  886. label=_('Has console server ports'),
  887. )
  888. power_ports = django_filters.BooleanFilter(
  889. method='_power_ports',
  890. label=_('Has power ports'),
  891. )
  892. power_outlets = django_filters.BooleanFilter(
  893. method='_power_outlets',
  894. label=_('Has power outlets'),
  895. )
  896. interfaces = django_filters.BooleanFilter(
  897. method='_interfaces',
  898. label=_('Has interfaces'),
  899. )
  900. pass_through_ports = django_filters.BooleanFilter(
  901. method='_pass_through_ports',
  902. label=_('Has pass-through ports'),
  903. )
  904. module_bays = django_filters.BooleanFilter(
  905. method='_module_bays',
  906. label=_('Has module bays'),
  907. )
  908. device_bays = django_filters.BooleanFilter(
  909. method='_device_bays',
  910. label=_('Has device bays'),
  911. )
  912. oob_ip_id = django_filters.ModelMultipleChoiceFilter(
  913. field_name='oob_ip',
  914. queryset=IPAddress.objects.all(),
  915. label=_('OOB IP (ID)'),
  916. )
  917. class Meta:
  918. model = Device
  919. fields = [
  920. 'id', 'asset_tag', 'face', 'position', 'latitude', 'longitude', 'airflow', 'vc_position', 'vc_priority',
  921. 'description',
  922. ]
  923. def search(self, queryset, name, value):
  924. if not value.strip():
  925. return queryset
  926. return queryset.filter(
  927. Q(name__icontains=value) |
  928. Q(serial__icontains=value.strip()) |
  929. Q(inventoryitems__serial__icontains=value.strip()) |
  930. Q(asset_tag__icontains=value.strip()) |
  931. Q(description__icontains=value.strip()) |
  932. Q(comments__icontains=value) |
  933. Q(primary_ip4__address__startswith=value) |
  934. Q(primary_ip6__address__startswith=value)
  935. ).distinct()
  936. def _has_primary_ip(self, queryset, name, value):
  937. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  938. if value:
  939. return queryset.filter(params)
  940. return queryset.exclude(params)
  941. def _has_oob_ip(self, queryset, name, value):
  942. params = Q(oob_ip__isnull=False)
  943. if value:
  944. return queryset.filter(params)
  945. return queryset.exclude(params)
  946. def _virtual_chassis_member(self, queryset, name, value):
  947. return queryset.exclude(virtual_chassis__isnull=value)
  948. def _console_ports(self, queryset, name, value):
  949. return queryset.exclude(consoleports__isnull=value)
  950. def _console_server_ports(self, queryset, name, value):
  951. return queryset.exclude(consoleserverports__isnull=value)
  952. def _power_ports(self, queryset, name, value):
  953. return queryset.exclude(powerports__isnull=value)
  954. def _power_outlets(self, queryset, name, value):
  955. return queryset.exclude(poweroutlets__isnull=value)
  956. def _interfaces(self, queryset, name, value):
  957. return queryset.exclude(interfaces__isnull=value)
  958. def _pass_through_ports(self, queryset, name, value):
  959. return queryset.exclude(
  960. frontports__isnull=value,
  961. rearports__isnull=value
  962. )
  963. def _module_bays(self, queryset, name, value):
  964. return queryset.exclude(modulebays__isnull=value)
  965. def _device_bays(self, queryset, name, value):
  966. return queryset.exclude(devicebays__isnull=value)
  967. class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
  968. device_id = django_filters.ModelMultipleChoiceFilter(
  969. field_name='device',
  970. queryset=Device.objects.all(),
  971. label='VDC (ID)',
  972. )
  973. device = django_filters.ModelMultipleChoiceFilter(
  974. field_name='device',
  975. queryset=Device.objects.all(),
  976. label='Device model',
  977. )
  978. status = django_filters.MultipleChoiceFilter(
  979. choices=VirtualDeviceContextStatusChoices
  980. )
  981. has_primary_ip = django_filters.BooleanFilter(
  982. method='_has_primary_ip',
  983. label='Has a primary IP',
  984. )
  985. class Meta:
  986. model = VirtualDeviceContext
  987. fields = ['id', 'device', 'name', 'description']
  988. def search(self, queryset, name, value):
  989. if not value.strip():
  990. return queryset
  991. qs_filter = (
  992. Q(name__icontains=value) |
  993. Q(description__icontains=value)
  994. )
  995. try:
  996. qs_filter |= Q(identifier=int(value))
  997. except ValueError:
  998. pass
  999. return queryset.filter(qs_filter).distinct()
  1000. def _has_primary_ip(self, queryset, name, value):
  1001. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  1002. if value:
  1003. return queryset.filter(params)
  1004. return queryset.exclude(params)
  1005. class ModuleFilterSet(NetBoxModelFilterSet):
  1006. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1007. field_name='module_type__manufacturer',
  1008. queryset=Manufacturer.objects.all(),
  1009. label=_('Manufacturer (ID)'),
  1010. )
  1011. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1012. field_name='module_type__manufacturer__slug',
  1013. queryset=Manufacturer.objects.all(),
  1014. to_field_name='slug',
  1015. label=_('Manufacturer (slug)'),
  1016. )
  1017. module_type_id = django_filters.ModelMultipleChoiceFilter(
  1018. field_name='module_type',
  1019. queryset=ModuleType.objects.all(),
  1020. label=_('Module type (ID)'),
  1021. )
  1022. module_type = django_filters.ModelMultipleChoiceFilter(
  1023. field_name='module_type__model',
  1024. queryset=ModuleType.objects.all(),
  1025. to_field_name='model',
  1026. label=_('Module type (model)'),
  1027. )
  1028. module_bay_id = django_filters.ModelMultipleChoiceFilter(
  1029. field_name='module_bay',
  1030. queryset=ModuleBay.objects.all(),
  1031. to_field_name='id',
  1032. label=_('Module Bay (ID)')
  1033. )
  1034. device_id = django_filters.ModelMultipleChoiceFilter(
  1035. queryset=Device.objects.all(),
  1036. label=_('Device (ID)'),
  1037. )
  1038. status = django_filters.MultipleChoiceFilter(
  1039. choices=ModuleStatusChoices,
  1040. null_value=None
  1041. )
  1042. serial = MultiValueCharFilter(
  1043. lookup_expr='iexact'
  1044. )
  1045. class Meta:
  1046. model = Module
  1047. fields = ['id', 'status', 'asset_tag', 'description']
  1048. def search(self, queryset, name, value):
  1049. if not value.strip():
  1050. return queryset
  1051. return queryset.filter(
  1052. Q(device__name__icontains=value.strip()) |
  1053. Q(serial__icontains=value.strip()) |
  1054. Q(asset_tag__icontains=value.strip()) |
  1055. Q(description__icontains=value) |
  1056. Q(comments__icontains=value)
  1057. ).distinct()
  1058. class DeviceComponentFilterSet(django_filters.FilterSet):
  1059. q = django_filters.CharFilter(
  1060. method='search',
  1061. label=_('Search'),
  1062. )
  1063. region_id = TreeNodeMultipleChoiceFilter(
  1064. queryset=Region.objects.all(),
  1065. field_name='device__site__region',
  1066. lookup_expr='in',
  1067. label=_('Region (ID)'),
  1068. )
  1069. region = TreeNodeMultipleChoiceFilter(
  1070. queryset=Region.objects.all(),
  1071. field_name='device__site__region',
  1072. lookup_expr='in',
  1073. to_field_name='slug',
  1074. label=_('Region (slug)'),
  1075. )
  1076. site_group_id = TreeNodeMultipleChoiceFilter(
  1077. queryset=SiteGroup.objects.all(),
  1078. field_name='device__site__group',
  1079. lookup_expr='in',
  1080. label=_('Site group (ID)'),
  1081. )
  1082. site_group = TreeNodeMultipleChoiceFilter(
  1083. queryset=SiteGroup.objects.all(),
  1084. field_name='device__site__group',
  1085. lookup_expr='in',
  1086. to_field_name='slug',
  1087. label=_('Site group (slug)'),
  1088. )
  1089. site_id = django_filters.ModelMultipleChoiceFilter(
  1090. field_name='device__site',
  1091. queryset=Site.objects.all(),
  1092. label=_('Site (ID)'),
  1093. )
  1094. site = django_filters.ModelMultipleChoiceFilter(
  1095. field_name='device__site__slug',
  1096. queryset=Site.objects.all(),
  1097. to_field_name='slug',
  1098. label=_('Site name (slug)'),
  1099. )
  1100. location_id = django_filters.ModelMultipleChoiceFilter(
  1101. field_name='device__location',
  1102. queryset=Location.objects.all(),
  1103. label=_('Location (ID)'),
  1104. )
  1105. location = django_filters.ModelMultipleChoiceFilter(
  1106. field_name='device__location__slug',
  1107. queryset=Location.objects.all(),
  1108. to_field_name='slug',
  1109. label=_('Location (slug)'),
  1110. )
  1111. rack_id = django_filters.ModelMultipleChoiceFilter(
  1112. field_name='device__rack',
  1113. queryset=Rack.objects.all(),
  1114. label=_('Rack (ID)'),
  1115. )
  1116. rack = django_filters.ModelMultipleChoiceFilter(
  1117. field_name='device__rack__name',
  1118. queryset=Rack.objects.all(),
  1119. to_field_name='name',
  1120. label=_('Rack (name)'),
  1121. )
  1122. device_id = django_filters.ModelMultipleChoiceFilter(
  1123. queryset=Device.objects.all(),
  1124. label=_('Device (ID)'),
  1125. )
  1126. device = django_filters.ModelMultipleChoiceFilter(
  1127. field_name='device__name',
  1128. queryset=Device.objects.all(),
  1129. to_field_name='name',
  1130. label=_('Device (name)'),
  1131. )
  1132. device_type_id = django_filters.ModelMultipleChoiceFilter(
  1133. field_name='device__device_type',
  1134. queryset=DeviceType.objects.all(),
  1135. label=_('Device type (ID)'),
  1136. )
  1137. device_type = django_filters.ModelMultipleChoiceFilter(
  1138. field_name='device__device_type__model',
  1139. queryset=DeviceType.objects.all(),
  1140. to_field_name='model',
  1141. label=_('Device type (model)'),
  1142. )
  1143. role_id = django_filters.ModelMultipleChoiceFilter(
  1144. field_name='device__role',
  1145. queryset=DeviceRole.objects.all(),
  1146. label=_('Device role (ID)'),
  1147. )
  1148. role = django_filters.ModelMultipleChoiceFilter(
  1149. field_name='device__role__slug',
  1150. queryset=DeviceRole.objects.all(),
  1151. to_field_name='slug',
  1152. label=_('Device role (slug)'),
  1153. )
  1154. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  1155. field_name='device__virtual_chassis',
  1156. queryset=VirtualChassis.objects.all(),
  1157. label=_('Virtual Chassis (ID)')
  1158. )
  1159. virtual_chassis = django_filters.ModelMultipleChoiceFilter(
  1160. field_name='device__virtual_chassis__name',
  1161. queryset=VirtualChassis.objects.all(),
  1162. to_field_name='name',
  1163. label=_('Virtual Chassis'),
  1164. )
  1165. # TODO: Remove in v4.0
  1166. device_role_id = django_filters.ModelMultipleChoiceFilter(
  1167. field_name='device__role',
  1168. queryset=DeviceRole.objects.all(),
  1169. label=_('Device role (ID)'),
  1170. )
  1171. device_role = django_filters.ModelMultipleChoiceFilter(
  1172. field_name='device__role__slug',
  1173. queryset=DeviceRole.objects.all(),
  1174. to_field_name='slug',
  1175. label=_('Device role (slug)'),
  1176. )
  1177. def search(self, queryset, name, value):
  1178. if not value.strip():
  1179. return queryset
  1180. return queryset.filter(
  1181. Q(name__icontains=value) |
  1182. Q(label__icontains=value) |
  1183. Q(description__icontains=value)
  1184. )
  1185. class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
  1186. """
  1187. Extends DeviceComponentFilterSet to add a module_id filter for components
  1188. which can be associated with a particular module within a device.
  1189. """
  1190. module_id = django_filters.ModelMultipleChoiceFilter(
  1191. queryset=Module.objects.all(),
  1192. label=_('Module (ID)'),
  1193. )
  1194. class CabledObjectFilterSet(django_filters.FilterSet):
  1195. cabled = django_filters.BooleanFilter(
  1196. field_name='cable',
  1197. lookup_expr='isnull',
  1198. exclude=True
  1199. )
  1200. occupied = django_filters.BooleanFilter(
  1201. method='filter_occupied'
  1202. )
  1203. def filter_occupied(self, queryset, name, value):
  1204. if value:
  1205. return queryset.filter(Q(cable__isnull=False) | Q(mark_connected=True))
  1206. else:
  1207. return queryset.filter(cable__isnull=True, mark_connected=False)
  1208. class PathEndpointFilterSet(django_filters.FilterSet):
  1209. connected = django_filters.BooleanFilter(
  1210. method='filter_connected'
  1211. )
  1212. def filter_connected(self, queryset, name, value):
  1213. if value:
  1214. return queryset.filter(_path__is_active=True)
  1215. else:
  1216. return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
  1217. class ConsolePortFilterSet(
  1218. ModularDeviceComponentFilterSet,
  1219. NetBoxModelFilterSet,
  1220. CabledObjectFilterSet,
  1221. PathEndpointFilterSet
  1222. ):
  1223. type = django_filters.MultipleChoiceFilter(
  1224. choices=ConsolePortTypeChoices,
  1225. null_value=None
  1226. )
  1227. class Meta:
  1228. model = ConsolePort
  1229. fields = ['id', 'name', 'label', 'description', 'cable_end']
  1230. class ConsoleServerPortFilterSet(
  1231. ModularDeviceComponentFilterSet,
  1232. NetBoxModelFilterSet,
  1233. CabledObjectFilterSet,
  1234. PathEndpointFilterSet
  1235. ):
  1236. type = django_filters.MultipleChoiceFilter(
  1237. choices=ConsolePortTypeChoices,
  1238. null_value=None
  1239. )
  1240. class Meta:
  1241. model = ConsoleServerPort
  1242. fields = ['id', 'name', 'label', 'description', 'cable_end']
  1243. class PowerPortFilterSet(
  1244. ModularDeviceComponentFilterSet,
  1245. NetBoxModelFilterSet,
  1246. CabledObjectFilterSet,
  1247. PathEndpointFilterSet
  1248. ):
  1249. type = django_filters.MultipleChoiceFilter(
  1250. choices=PowerPortTypeChoices,
  1251. null_value=None
  1252. )
  1253. class Meta:
  1254. model = PowerPort
  1255. fields = ['id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description', 'cable_end']
  1256. class PowerOutletFilterSet(
  1257. ModularDeviceComponentFilterSet,
  1258. NetBoxModelFilterSet,
  1259. CabledObjectFilterSet,
  1260. PathEndpointFilterSet
  1261. ):
  1262. type = django_filters.MultipleChoiceFilter(
  1263. choices=PowerOutletTypeChoices,
  1264. null_value=None
  1265. )
  1266. feed_leg = django_filters.MultipleChoiceFilter(
  1267. choices=PowerOutletFeedLegChoices,
  1268. null_value=None
  1269. )
  1270. class Meta:
  1271. model = PowerOutlet
  1272. fields = ['id', 'name', 'label', 'feed_leg', 'description', 'cable_end']
  1273. class CommonInterfaceFilterSet(django_filters.FilterSet):
  1274. vlan_id = django_filters.CharFilter(
  1275. method='filter_vlan_id',
  1276. label=_('Assigned VLAN')
  1277. )
  1278. vlan = django_filters.CharFilter(
  1279. method='filter_vlan',
  1280. label=_('Assigned VID')
  1281. )
  1282. vrf_id = django_filters.ModelMultipleChoiceFilter(
  1283. field_name='vrf',
  1284. queryset=VRF.objects.all(),
  1285. label=_('VRF'),
  1286. )
  1287. vrf = django_filters.ModelMultipleChoiceFilter(
  1288. field_name='vrf__rd',
  1289. queryset=VRF.objects.all(),
  1290. to_field_name='rd',
  1291. label=_('VRF (RD)'),
  1292. )
  1293. l2vpn_id = django_filters.ModelMultipleChoiceFilter(
  1294. field_name='l2vpn_terminations__l2vpn',
  1295. queryset=L2VPN.objects.all(),
  1296. label=_('L2VPN (ID)'),
  1297. )
  1298. l2vpn = django_filters.ModelMultipleChoiceFilter(
  1299. field_name='l2vpn_terminations__l2vpn__identifier',
  1300. queryset=L2VPN.objects.all(),
  1301. to_field_name='identifier',
  1302. label=_('L2VPN'),
  1303. )
  1304. def filter_vlan_id(self, queryset, name, value):
  1305. value = value.strip()
  1306. if not value:
  1307. return queryset
  1308. return queryset.filter(
  1309. Q(untagged_vlan_id=value) |
  1310. Q(tagged_vlans=value)
  1311. )
  1312. def filter_vlan(self, queryset, name, value):
  1313. value = value.strip()
  1314. if not value:
  1315. return queryset
  1316. return queryset.filter(
  1317. Q(untagged_vlan_id__vid=value) |
  1318. Q(tagged_vlans__vid=value)
  1319. )
  1320. class InterfaceFilterSet(
  1321. ModularDeviceComponentFilterSet,
  1322. NetBoxModelFilterSet,
  1323. CabledObjectFilterSet,
  1324. PathEndpointFilterSet,
  1325. CommonInterfaceFilterSet
  1326. ):
  1327. virtual_chassis_member = MultiValueCharFilter(
  1328. method='filter_virtual_chassis_member',
  1329. field_name='name',
  1330. label=_('Virtual Chassis Interfaces for Device')
  1331. )
  1332. virtual_chassis_member_id = MultiValueNumberFilter(
  1333. method='filter_virtual_chassis_member',
  1334. field_name='pk',
  1335. label=_('Virtual Chassis Interfaces for Device (ID)')
  1336. )
  1337. kind = django_filters.CharFilter(
  1338. method='filter_kind',
  1339. label=_('Kind of interface'),
  1340. )
  1341. parent_id = django_filters.ModelMultipleChoiceFilter(
  1342. field_name='parent',
  1343. queryset=Interface.objects.all(),
  1344. label=_('Parent interface (ID)'),
  1345. )
  1346. bridge_id = django_filters.ModelMultipleChoiceFilter(
  1347. field_name='bridge',
  1348. queryset=Interface.objects.all(),
  1349. label=_('Bridged interface (ID)'),
  1350. )
  1351. lag_id = django_filters.ModelMultipleChoiceFilter(
  1352. field_name='lag',
  1353. queryset=Interface.objects.all(),
  1354. label=_('LAG interface (ID)'),
  1355. )
  1356. speed = MultiValueNumberFilter()
  1357. duplex = django_filters.MultipleChoiceFilter(
  1358. choices=InterfaceDuplexChoices
  1359. )
  1360. mac_address = MultiValueMACAddressFilter()
  1361. wwn = MultiValueWWNFilter()
  1362. poe_mode = django_filters.MultipleChoiceFilter(
  1363. choices=InterfacePoEModeChoices
  1364. )
  1365. poe_type = django_filters.MultipleChoiceFilter(
  1366. choices=InterfacePoETypeChoices
  1367. )
  1368. type = django_filters.MultipleChoiceFilter(
  1369. choices=InterfaceTypeChoices,
  1370. null_value=None
  1371. )
  1372. rf_role = django_filters.MultipleChoiceFilter(
  1373. choices=WirelessRoleChoices
  1374. )
  1375. rf_channel = django_filters.MultipleChoiceFilter(
  1376. choices=WirelessChannelChoices
  1377. )
  1378. vdc_id = django_filters.ModelMultipleChoiceFilter(
  1379. field_name='vdcs',
  1380. queryset=VirtualDeviceContext.objects.all(),
  1381. label='Virtual Device Context',
  1382. )
  1383. vdc_identifier = django_filters.ModelMultipleChoiceFilter(
  1384. field_name='vdcs__identifier',
  1385. queryset=VirtualDeviceContext.objects.all(),
  1386. to_field_name='identifier',
  1387. label='Virtual Device Context (Identifier)',
  1388. )
  1389. vdc = django_filters.ModelMultipleChoiceFilter(
  1390. field_name='vdcs__name',
  1391. queryset=VirtualDeviceContext.objects.all(),
  1392. to_field_name='name',
  1393. label='Virtual Device Context',
  1394. )
  1395. class Meta:
  1396. model = Interface
  1397. fields = [
  1398. 'id', 'name', 'label', 'type', 'enabled', 'mtu', 'mgmt_only', 'poe_mode', 'poe_type', 'mode', 'rf_role',
  1399. 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'cable_end',
  1400. ]
  1401. def filter_virtual_chassis_member(self, queryset, name, value):
  1402. try:
  1403. vc_interface_ids = []
  1404. for device in Device.objects.filter(**{f'{name}__in': value}):
  1405. vc_interface_ids.extend(device.vc_interfaces(if_master=False).values_list('id', flat=True))
  1406. return queryset.filter(pk__in=vc_interface_ids)
  1407. except Device.DoesNotExist:
  1408. return queryset.none()
  1409. def filter_kind(self, queryset, name, value):
  1410. value = value.strip().lower()
  1411. return {
  1412. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  1413. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  1414. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  1415. }.get(value, queryset.none())
  1416. class FrontPortFilterSet(
  1417. ModularDeviceComponentFilterSet,
  1418. NetBoxModelFilterSet,
  1419. CabledObjectFilterSet
  1420. ):
  1421. type = django_filters.MultipleChoiceFilter(
  1422. choices=PortTypeChoices,
  1423. null_value=None
  1424. )
  1425. class Meta:
  1426. model = FrontPort
  1427. fields = ['id', 'name', 'label', 'type', 'color', 'description', 'cable_end']
  1428. class RearPortFilterSet(
  1429. ModularDeviceComponentFilterSet,
  1430. NetBoxModelFilterSet,
  1431. CabledObjectFilterSet
  1432. ):
  1433. type = django_filters.MultipleChoiceFilter(
  1434. choices=PortTypeChoices,
  1435. null_value=None
  1436. )
  1437. class Meta:
  1438. model = RearPort
  1439. fields = ['id', 'name', 'label', 'type', 'color', 'positions', 'description', 'cable_end']
  1440. class ModuleBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1441. class Meta:
  1442. model = ModuleBay
  1443. fields = ['id', 'name', 'label', 'description']
  1444. class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1445. class Meta:
  1446. model = DeviceBay
  1447. fields = ['id', 'name', 'label', 'description']
  1448. class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1449. parent_id = django_filters.ModelMultipleChoiceFilter(
  1450. queryset=InventoryItem.objects.all(),
  1451. label=_('Parent inventory item (ID)'),
  1452. )
  1453. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1454. queryset=Manufacturer.objects.all(),
  1455. label=_('Manufacturer (ID)'),
  1456. )
  1457. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1458. field_name='manufacturer__slug',
  1459. queryset=Manufacturer.objects.all(),
  1460. to_field_name='slug',
  1461. label=_('Manufacturer (slug)'),
  1462. )
  1463. role_id = django_filters.ModelMultipleChoiceFilter(
  1464. queryset=InventoryItemRole.objects.all(),
  1465. label=_('Role (ID)'),
  1466. )
  1467. role = django_filters.ModelMultipleChoiceFilter(
  1468. field_name='role__slug',
  1469. queryset=InventoryItemRole.objects.all(),
  1470. to_field_name='slug',
  1471. label=_('Role (slug)'),
  1472. )
  1473. component_type = ContentTypeFilter()
  1474. component_id = MultiValueNumberFilter()
  1475. serial = MultiValueCharFilter(
  1476. lookup_expr='iexact'
  1477. )
  1478. class Meta:
  1479. model = InventoryItem
  1480. fields = ['id', 'name', 'label', 'part_id', 'asset_tag', 'discovered']
  1481. def search(self, queryset, name, value):
  1482. if not value.strip():
  1483. return queryset
  1484. qs_filter = (
  1485. Q(name__icontains=value) |
  1486. Q(part_id__icontains=value) |
  1487. Q(serial__icontains=value) |
  1488. Q(asset_tag__icontains=value) |
  1489. Q(description__icontains=value)
  1490. )
  1491. return queryset.filter(qs_filter)
  1492. class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
  1493. class Meta:
  1494. model = InventoryItemRole
  1495. fields = ['id', 'name', 'slug', 'color', 'description']
  1496. class VirtualChassisFilterSet(NetBoxModelFilterSet):
  1497. master_id = django_filters.ModelMultipleChoiceFilter(
  1498. queryset=Device.objects.all(),
  1499. label=_('Master (ID)'),
  1500. )
  1501. master = django_filters.ModelMultipleChoiceFilter(
  1502. field_name='master__name',
  1503. queryset=Device.objects.all(),
  1504. to_field_name='name',
  1505. label=_('Master (name)'),
  1506. )
  1507. region_id = TreeNodeMultipleChoiceFilter(
  1508. queryset=Region.objects.all(),
  1509. field_name='master__site__region',
  1510. lookup_expr='in',
  1511. label=_('Region (ID)'),
  1512. )
  1513. region = TreeNodeMultipleChoiceFilter(
  1514. queryset=Region.objects.all(),
  1515. field_name='master__site__region',
  1516. lookup_expr='in',
  1517. to_field_name='slug',
  1518. label=_('Region (slug)'),
  1519. )
  1520. site_group_id = TreeNodeMultipleChoiceFilter(
  1521. queryset=SiteGroup.objects.all(),
  1522. field_name='master__site__group',
  1523. lookup_expr='in',
  1524. label=_('Site group (ID)'),
  1525. )
  1526. site_group = TreeNodeMultipleChoiceFilter(
  1527. queryset=SiteGroup.objects.all(),
  1528. field_name='master__site__group',
  1529. lookup_expr='in',
  1530. to_field_name='slug',
  1531. label=_('Site group (slug)'),
  1532. )
  1533. site_id = django_filters.ModelMultipleChoiceFilter(
  1534. field_name='master__site',
  1535. queryset=Site.objects.all(),
  1536. label=_('Site (ID)'),
  1537. )
  1538. site = django_filters.ModelMultipleChoiceFilter(
  1539. field_name='master__site__slug',
  1540. queryset=Site.objects.all(),
  1541. to_field_name='slug',
  1542. label=_('Site name (slug)'),
  1543. )
  1544. tenant_id = django_filters.ModelMultipleChoiceFilter(
  1545. field_name='master__tenant',
  1546. queryset=Tenant.objects.all(),
  1547. label=_('Tenant (ID)'),
  1548. )
  1549. tenant = django_filters.ModelMultipleChoiceFilter(
  1550. field_name='master__tenant__slug',
  1551. queryset=Tenant.objects.all(),
  1552. to_field_name='slug',
  1553. label=_('Tenant (slug)'),
  1554. )
  1555. class Meta:
  1556. model = VirtualChassis
  1557. fields = ['id', 'domain', 'name', 'description']
  1558. def search(self, queryset, name, value):
  1559. if not value.strip():
  1560. return queryset
  1561. qs_filter = (
  1562. Q(name__icontains=value) |
  1563. Q(description__icontains=value) |
  1564. Q(members__name__icontains=value) |
  1565. Q(domain__icontains=value)
  1566. )
  1567. return queryset.filter(qs_filter).distinct()
  1568. class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
  1569. termination_a_type = ContentTypeFilter(
  1570. field_name='terminations__termination_type'
  1571. )
  1572. termination_a_id = MultiValueNumberFilter(
  1573. method='filter_by_cable_end_a',
  1574. field_name='terminations__termination_id'
  1575. )
  1576. termination_b_type = ContentTypeFilter(
  1577. field_name='terminations__termination_type'
  1578. )
  1579. termination_b_id = MultiValueNumberFilter(
  1580. method='filter_by_cable_end_b',
  1581. field_name='terminations__termination_id'
  1582. )
  1583. unterminated = django_filters.BooleanFilter(
  1584. method='_unterminated',
  1585. label=_('Unterminated'),
  1586. )
  1587. type = django_filters.MultipleChoiceFilter(
  1588. choices=CableTypeChoices
  1589. )
  1590. status = django_filters.MultipleChoiceFilter(
  1591. choices=LinkStatusChoices
  1592. )
  1593. color = django_filters.MultipleChoiceFilter(
  1594. choices=ColorChoices
  1595. )
  1596. device_id = MultiValueNumberFilter(
  1597. method='filter_by_termination'
  1598. )
  1599. device = MultiValueCharFilter(
  1600. method='filter_by_termination',
  1601. field_name='device__name'
  1602. )
  1603. rack_id = MultiValueNumberFilter(
  1604. method='filter_by_termination',
  1605. field_name='rack_id'
  1606. )
  1607. rack = MultiValueCharFilter(
  1608. method='filter_by_termination',
  1609. field_name='rack__name'
  1610. )
  1611. location_id = MultiValueNumberFilter(
  1612. method='filter_by_termination',
  1613. field_name='location_id'
  1614. )
  1615. location = MultiValueCharFilter(
  1616. method='filter_by_termination',
  1617. field_name='location__name'
  1618. )
  1619. site_id = MultiValueNumberFilter(
  1620. method='filter_by_termination',
  1621. field_name='site_id'
  1622. )
  1623. site = MultiValueCharFilter(
  1624. method='filter_by_termination',
  1625. field_name='site__slug'
  1626. )
  1627. class Meta:
  1628. model = Cable
  1629. fields = ['id', 'label', 'length', 'length_unit', 'description']
  1630. def search(self, queryset, name, value):
  1631. if not value.strip():
  1632. return queryset
  1633. qs_filter = (
  1634. Q(label__icontains=value) |
  1635. Q(description__icontains=value)
  1636. )
  1637. return queryset.filter(qs_filter)
  1638. def filter_by_termination(self, queryset, name, value):
  1639. # Filter by a related object cached on CableTermination. Note the underscore preceding the field name.
  1640. # Supported objects: device, rack, location, site
  1641. return queryset.filter(**{f'terminations___{name}__in': value}).distinct()
  1642. def filter_by_cable_end(self, queryset, name, value, side):
  1643. # Filter by termination id and cable_end type
  1644. return queryset.filter(**{f'{name}__in': value, 'terminations__cable_end': side}).distinct()
  1645. def filter_by_cable_end_a(self, queryset, name, value):
  1646. # Filter by termination id and cable_end type
  1647. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_A)
  1648. def filter_by_cable_end_b(self, queryset, name, value):
  1649. # Filter by termination id and cable_end type
  1650. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_B)
  1651. def _unterminated(self, queryset, name, value):
  1652. if value:
  1653. terminated_ids = (
  1654. queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A)
  1655. .filter(terminations__cable_end=CableEndChoices.SIDE_B)
  1656. .values("id")
  1657. )
  1658. return queryset.exclude(id__in=terminated_ids)
  1659. else:
  1660. return queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A).filter(
  1661. terminations__cable_end=CableEndChoices.SIDE_B
  1662. )
  1663. class CableTerminationFilterSet(BaseFilterSet):
  1664. termination_type = ContentTypeFilter()
  1665. class Meta:
  1666. model = CableTermination
  1667. fields = ['id', 'cable', 'cable_end', 'termination_type', 'termination_id']
  1668. class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
  1669. region_id = TreeNodeMultipleChoiceFilter(
  1670. queryset=Region.objects.all(),
  1671. field_name='site__region',
  1672. lookup_expr='in',
  1673. label=_('Region (ID)'),
  1674. )
  1675. region = TreeNodeMultipleChoiceFilter(
  1676. queryset=Region.objects.all(),
  1677. field_name='site__region',
  1678. lookup_expr='in',
  1679. to_field_name='slug',
  1680. label=_('Region (slug)'),
  1681. )
  1682. site_group_id = TreeNodeMultipleChoiceFilter(
  1683. queryset=SiteGroup.objects.all(),
  1684. field_name='site__group',
  1685. lookup_expr='in',
  1686. label=_('Site group (ID)'),
  1687. )
  1688. site_group = TreeNodeMultipleChoiceFilter(
  1689. queryset=SiteGroup.objects.all(),
  1690. field_name='site__group',
  1691. lookup_expr='in',
  1692. to_field_name='slug',
  1693. label=_('Site group (slug)'),
  1694. )
  1695. site_id = django_filters.ModelMultipleChoiceFilter(
  1696. queryset=Site.objects.all(),
  1697. label=_('Site (ID)'),
  1698. )
  1699. site = django_filters.ModelMultipleChoiceFilter(
  1700. field_name='site__slug',
  1701. queryset=Site.objects.all(),
  1702. to_field_name='slug',
  1703. label=_('Site name (slug)'),
  1704. )
  1705. location_id = TreeNodeMultipleChoiceFilter(
  1706. queryset=Location.objects.all(),
  1707. field_name='location',
  1708. lookup_expr='in',
  1709. label=_('Location (ID)'),
  1710. )
  1711. class Meta:
  1712. model = PowerPanel
  1713. fields = ['id', 'name', 'description']
  1714. def search(self, queryset, name, value):
  1715. if not value.strip():
  1716. return queryset
  1717. qs_filter = (
  1718. Q(name__icontains=value) |
  1719. Q(description__icontains=value)
  1720. )
  1721. return queryset.filter(qs_filter)
  1722. class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
  1723. region_id = TreeNodeMultipleChoiceFilter(
  1724. queryset=Region.objects.all(),
  1725. field_name='power_panel__site__region',
  1726. lookup_expr='in',
  1727. label=_('Region (ID)'),
  1728. )
  1729. region = TreeNodeMultipleChoiceFilter(
  1730. queryset=Region.objects.all(),
  1731. field_name='power_panel__site__region',
  1732. lookup_expr='in',
  1733. to_field_name='slug',
  1734. label=_('Region (slug)'),
  1735. )
  1736. site_group_id = TreeNodeMultipleChoiceFilter(
  1737. queryset=SiteGroup.objects.all(),
  1738. field_name='power_panel__site__group',
  1739. lookup_expr='in',
  1740. label=_('Site group (ID)'),
  1741. )
  1742. site_group = TreeNodeMultipleChoiceFilter(
  1743. queryset=SiteGroup.objects.all(),
  1744. field_name='power_panel__site__group',
  1745. lookup_expr='in',
  1746. to_field_name='slug',
  1747. label=_('Site group (slug)'),
  1748. )
  1749. site_id = django_filters.ModelMultipleChoiceFilter(
  1750. field_name='power_panel__site',
  1751. queryset=Site.objects.all(),
  1752. label=_('Site (ID)'),
  1753. )
  1754. site = django_filters.ModelMultipleChoiceFilter(
  1755. field_name='power_panel__site__slug',
  1756. queryset=Site.objects.all(),
  1757. to_field_name='slug',
  1758. label=_('Site name (slug)'),
  1759. )
  1760. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  1761. queryset=PowerPanel.objects.all(),
  1762. label=_('Power panel (ID)'),
  1763. )
  1764. rack_id = django_filters.ModelMultipleChoiceFilter(
  1765. field_name='rack',
  1766. queryset=Rack.objects.all(),
  1767. label=_('Rack (ID)'),
  1768. )
  1769. status = django_filters.MultipleChoiceFilter(
  1770. choices=PowerFeedStatusChoices,
  1771. null_value=None
  1772. )
  1773. class Meta:
  1774. model = PowerFeed
  1775. fields = [
  1776. 'id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', 'cable_end',
  1777. 'description',
  1778. ]
  1779. def search(self, queryset, name, value):
  1780. if not value.strip():
  1781. return queryset
  1782. qs_filter = (
  1783. Q(name__icontains=value) |
  1784. Q(description__icontains=value) |
  1785. Q(power_panel__name__icontains=value) |
  1786. Q(comments__icontains=value)
  1787. )
  1788. return queryset.filter(qs_filter)
  1789. #
  1790. # Connection filter sets
  1791. #
  1792. class ConnectionFilterSet(BaseFilterSet):
  1793. q = django_filters.CharFilter(
  1794. method='search',
  1795. label=_('Search'),
  1796. )
  1797. site_id = MultiValueNumberFilter(
  1798. method='filter_connections',
  1799. field_name='device__site_id'
  1800. )
  1801. site = MultiValueCharFilter(
  1802. method='filter_connections',
  1803. field_name='device__site__slug'
  1804. )
  1805. device_id = MultiValueNumberFilter(
  1806. method='filter_connections',
  1807. field_name='device_id'
  1808. )
  1809. device = MultiValueCharFilter(
  1810. method='filter_connections',
  1811. field_name='device__name'
  1812. )
  1813. def filter_connections(self, queryset, name, value):
  1814. if not value:
  1815. return queryset
  1816. return queryset.filter(**{f'{name}__in': value})
  1817. def search(self, queryset, name, value):
  1818. if not value.strip():
  1819. return queryset
  1820. qs_filter = (
  1821. Q(device__name__icontains=value) |
  1822. Q(cable__label__icontains=value)
  1823. )
  1824. return queryset.filter(qs_filter)
  1825. class ConsoleConnectionFilterSet(ConnectionFilterSet):
  1826. class Meta:
  1827. model = ConsolePort
  1828. fields = ['name']
  1829. class PowerConnectionFilterSet(ConnectionFilterSet):
  1830. class Meta:
  1831. model = PowerPort
  1832. fields = ['name']
  1833. class InterfaceConnectionFilterSet(ConnectionFilterSet):
  1834. class Meta:
  1835. model = Interface
  1836. fields = []