filtersets.py 72 KB

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