filtersets.py 61 KB

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