filters.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. from __future__ import unicode_literals
  2. import django_filters
  3. from django.contrib.auth.models import User
  4. from django.db.models import Q
  5. from netaddr import EUI
  6. from netaddr.core import AddrFormatError
  7. from extras.filters import CustomFieldFilterSet
  8. from tenancy.models import Tenant
  9. from utilities.filters import NullableCharFieldFilter, NumericInFilter
  10. from virtualization.models import Cluster
  11. from .constants import (
  12. DEVICE_STATUS_CHOICES, IFACE_FF_LAG, NONCONNECTABLE_IFACE_TYPES, VIRTUAL_IFACE_TYPES, WIRELESS_IFACE_TYPES,
  13. )
  14. from .models import (
  15. ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  16. DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate, Manufacturer,
  17. InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
  18. RackReservation, RackRole, Region, Site, VirtualChassis, VCMembership,
  19. )
  20. class RegionFilter(django_filters.FilterSet):
  21. parent_id = django_filters.ModelMultipleChoiceFilter(
  22. queryset=Region.objects.all(),
  23. label='Parent region (ID)',
  24. )
  25. parent = django_filters.ModelMultipleChoiceFilter(
  26. name='parent__slug',
  27. queryset=Region.objects.all(),
  28. to_field_name='slug',
  29. label='Parent region (slug)',
  30. )
  31. class Meta:
  32. model = Region
  33. fields = ['name', 'slug']
  34. class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
  35. id__in = NumericInFilter(name='id', lookup_expr='in')
  36. q = django_filters.CharFilter(
  37. method='search',
  38. label='Search',
  39. )
  40. region_id = django_filters.ModelMultipleChoiceFilter(
  41. queryset=Region.objects.all(),
  42. label='Region (ID)',
  43. )
  44. region = django_filters.ModelMultipleChoiceFilter(
  45. name='region__slug',
  46. queryset=Region.objects.all(),
  47. to_field_name='slug',
  48. label='Region (slug)',
  49. )
  50. tenant_id = django_filters.ModelMultipleChoiceFilter(
  51. queryset=Tenant.objects.all(),
  52. label='Tenant (ID)',
  53. )
  54. tenant = django_filters.ModelMultipleChoiceFilter(
  55. name='tenant__slug',
  56. queryset=Tenant.objects.all(),
  57. to_field_name='slug',
  58. label='Tenant (slug)',
  59. )
  60. class Meta:
  61. model = Site
  62. fields = ['q', 'name', 'slug', 'status', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email']
  63. def search(self, queryset, name, value):
  64. if not value.strip():
  65. return queryset
  66. qs_filter = (
  67. Q(name__icontains=value) |
  68. Q(facility__icontains=value) |
  69. Q(description__icontains=value) |
  70. Q(physical_address__icontains=value) |
  71. Q(shipping_address__icontains=value) |
  72. Q(contact_name__icontains=value) |
  73. Q(contact_phone__icontains=value) |
  74. Q(contact_email__icontains=value) |
  75. Q(comments__icontains=value)
  76. )
  77. try:
  78. qs_filter |= Q(asn=int(value.strip()))
  79. except ValueError:
  80. pass
  81. return queryset.filter(qs_filter)
  82. class RackGroupFilter(django_filters.FilterSet):
  83. site_id = django_filters.ModelMultipleChoiceFilter(
  84. queryset=Site.objects.all(),
  85. label='Site (ID)',
  86. )
  87. site = django_filters.ModelMultipleChoiceFilter(
  88. name='site__slug',
  89. queryset=Site.objects.all(),
  90. to_field_name='slug',
  91. label='Site (slug)',
  92. )
  93. class Meta:
  94. model = RackGroup
  95. fields = ['site_id', 'name', 'slug']
  96. class RackRoleFilter(django_filters.FilterSet):
  97. class Meta:
  98. model = RackRole
  99. fields = ['name', 'slug', 'color']
  100. class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
  101. id__in = NumericInFilter(name='id', lookup_expr='in')
  102. q = django_filters.CharFilter(
  103. method='search',
  104. label='Search',
  105. )
  106. facility_id = NullableCharFieldFilter()
  107. site_id = django_filters.ModelMultipleChoiceFilter(
  108. queryset=Site.objects.all(),
  109. label='Site (ID)',
  110. )
  111. site = django_filters.ModelMultipleChoiceFilter(
  112. name='site__slug',
  113. queryset=Site.objects.all(),
  114. to_field_name='slug',
  115. label='Site (slug)',
  116. )
  117. group_id = django_filters.ModelMultipleChoiceFilter(
  118. queryset=RackGroup.objects.all(),
  119. label='Group (ID)',
  120. )
  121. group = django_filters.ModelMultipleChoiceFilter(
  122. name='group__slug',
  123. queryset=RackGroup.objects.all(),
  124. to_field_name='slug',
  125. label='Group',
  126. )
  127. tenant_id = django_filters.ModelMultipleChoiceFilter(
  128. queryset=Tenant.objects.all(),
  129. label='Tenant (ID)',
  130. )
  131. tenant = django_filters.ModelMultipleChoiceFilter(
  132. name='tenant__slug',
  133. queryset=Tenant.objects.all(),
  134. to_field_name='slug',
  135. label='Tenant (slug)',
  136. )
  137. role_id = django_filters.ModelMultipleChoiceFilter(
  138. queryset=RackRole.objects.all(),
  139. label='Role (ID)',
  140. )
  141. role = django_filters.ModelMultipleChoiceFilter(
  142. name='role__slug',
  143. queryset=RackRole.objects.all(),
  144. to_field_name='slug',
  145. label='Role (slug)',
  146. )
  147. class Meta:
  148. model = Rack
  149. fields = ['name', 'serial', 'type', 'width', 'u_height', 'desc_units']
  150. def search(self, queryset, name, value):
  151. if not value.strip():
  152. return queryset
  153. return queryset.filter(
  154. Q(name__icontains=value) |
  155. Q(facility_id__icontains=value) |
  156. Q(serial__icontains=value.strip()) |
  157. Q(comments__icontains=value)
  158. )
  159. class RackReservationFilter(django_filters.FilterSet):
  160. id__in = NumericInFilter(name='id', lookup_expr='in')
  161. q = django_filters.CharFilter(
  162. method='search',
  163. label='Search',
  164. )
  165. rack_id = django_filters.ModelMultipleChoiceFilter(
  166. queryset=Rack.objects.all(),
  167. label='Rack (ID)',
  168. )
  169. site_id = django_filters.ModelMultipleChoiceFilter(
  170. name='rack__site',
  171. queryset=Site.objects.all(),
  172. label='Site (ID)',
  173. )
  174. site = django_filters.ModelMultipleChoiceFilter(
  175. name='rack__site__slug',
  176. queryset=Site.objects.all(),
  177. to_field_name='slug',
  178. label='Site (slug)',
  179. )
  180. group_id = django_filters.ModelMultipleChoiceFilter(
  181. name='rack__group',
  182. queryset=RackGroup.objects.all(),
  183. label='Group (ID)',
  184. )
  185. group = django_filters.ModelMultipleChoiceFilter(
  186. name='rack__group__slug',
  187. queryset=RackGroup.objects.all(),
  188. to_field_name='slug',
  189. label='Group',
  190. )
  191. tenant_id = django_filters.ModelMultipleChoiceFilter(
  192. queryset=Tenant.objects.all(),
  193. label='Tenant (ID)',
  194. )
  195. tenant = django_filters.ModelMultipleChoiceFilter(
  196. name='tenant__slug',
  197. queryset=Tenant.objects.all(),
  198. to_field_name='slug',
  199. label='Tenant (slug)',
  200. )
  201. user_id = django_filters.ModelMultipleChoiceFilter(
  202. queryset=User.objects.all(),
  203. label='User (ID)',
  204. )
  205. user = django_filters.ModelMultipleChoiceFilter(
  206. name='user',
  207. queryset=User.objects.all(),
  208. to_field_name='username',
  209. label='User (name)',
  210. )
  211. class Meta:
  212. model = RackReservation
  213. fields = ['created']
  214. def search(self, queryset, name, value):
  215. if not value.strip():
  216. return queryset
  217. return queryset.filter(
  218. Q(rack__name__icontains=value) |
  219. Q(rack__facility_id__icontains=value) |
  220. Q(user__username__icontains=value) |
  221. Q(description__icontains=value)
  222. )
  223. class ManufacturerFilter(django_filters.FilterSet):
  224. class Meta:
  225. model = Manufacturer
  226. fields = ['name', 'slug']
  227. class DeviceTypeFilter(CustomFieldFilterSet, django_filters.FilterSet):
  228. id__in = NumericInFilter(name='id', lookup_expr='in')
  229. q = django_filters.CharFilter(
  230. method='search',
  231. label='Search',
  232. )
  233. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  234. queryset=Manufacturer.objects.all(),
  235. label='Manufacturer (ID)',
  236. )
  237. manufacturer = django_filters.ModelMultipleChoiceFilter(
  238. name='manufacturer__slug',
  239. queryset=Manufacturer.objects.all(),
  240. to_field_name='slug',
  241. label='Manufacturer (slug)',
  242. )
  243. class Meta:
  244. model = DeviceType
  245. fields = [
  246. 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'is_console_server', 'is_pdu',
  247. 'is_network_device', 'subdevice_role',
  248. ]
  249. def search(self, queryset, name, value):
  250. if not value.strip():
  251. return queryset
  252. return queryset.filter(
  253. Q(manufacturer__name__icontains=value) |
  254. Q(model__icontains=value) |
  255. Q(part_number__icontains=value) |
  256. Q(comments__icontains=value)
  257. )
  258. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  259. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  260. queryset=DeviceType.objects.all(),
  261. name='device_type_id',
  262. label='Device type (ID)',
  263. )
  264. class ConsolePortTemplateFilter(DeviceTypeComponentFilterSet):
  265. class Meta:
  266. model = ConsolePortTemplate
  267. fields = ['name']
  268. class ConsoleServerPortTemplateFilter(DeviceTypeComponentFilterSet):
  269. class Meta:
  270. model = ConsoleServerPortTemplate
  271. fields = ['name']
  272. class PowerPortTemplateFilter(DeviceTypeComponentFilterSet):
  273. class Meta:
  274. model = PowerPortTemplate
  275. fields = ['name']
  276. class PowerOutletTemplateFilter(DeviceTypeComponentFilterSet):
  277. class Meta:
  278. model = PowerOutletTemplate
  279. fields = ['name']
  280. class InterfaceTemplateFilter(DeviceTypeComponentFilterSet):
  281. class Meta:
  282. model = InterfaceTemplate
  283. fields = ['name', 'form_factor', 'mgmt_only']
  284. class DeviceBayTemplateFilter(DeviceTypeComponentFilterSet):
  285. class Meta:
  286. model = DeviceBayTemplate
  287. fields = ['name']
  288. class DeviceRoleFilter(django_filters.FilterSet):
  289. class Meta:
  290. model = DeviceRole
  291. fields = ['name', 'slug', 'color', 'vm_role']
  292. class PlatformFilter(django_filters.FilterSet):
  293. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  294. name='manufacturer',
  295. queryset=Manufacturer.objects.all(),
  296. label='Manufacturer (ID)',
  297. )
  298. manufacturer = django_filters.ModelMultipleChoiceFilter(
  299. name='manufacturer__slug',
  300. queryset=Manufacturer.objects.all(),
  301. to_field_name='slug',
  302. label='Manufacturer (slug)',
  303. )
  304. class Meta:
  305. model = Platform
  306. fields = ['name', 'slug']
  307. class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
  308. id__in = NumericInFilter(name='id', lookup_expr='in')
  309. q = django_filters.CharFilter(
  310. method='search',
  311. label='Search',
  312. )
  313. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  314. name='device_type__manufacturer',
  315. queryset=Manufacturer.objects.all(),
  316. label='Manufacturer (ID)',
  317. )
  318. manufacturer = django_filters.ModelMultipleChoiceFilter(
  319. name='device_type__manufacturer__slug',
  320. queryset=Manufacturer.objects.all(),
  321. to_field_name='slug',
  322. label='Manufacturer (slug)',
  323. )
  324. device_type_id = django_filters.ModelMultipleChoiceFilter(
  325. queryset=DeviceType.objects.all(),
  326. label='Device type (ID)',
  327. )
  328. role_id = django_filters.ModelMultipleChoiceFilter(
  329. name='device_role_id',
  330. queryset=DeviceRole.objects.all(),
  331. label='Role (ID)',
  332. )
  333. role = django_filters.ModelMultipleChoiceFilter(
  334. name='device_role__slug',
  335. queryset=DeviceRole.objects.all(),
  336. to_field_name='slug',
  337. label='Role (slug)',
  338. )
  339. tenant_id = django_filters.ModelMultipleChoiceFilter(
  340. queryset=Tenant.objects.all(),
  341. label='Tenant (ID)',
  342. )
  343. tenant = django_filters.ModelMultipleChoiceFilter(
  344. name='tenant__slug',
  345. queryset=Tenant.objects.all(),
  346. to_field_name='slug',
  347. label='Tenant (slug)',
  348. )
  349. platform_id = django_filters.ModelMultipleChoiceFilter(
  350. queryset=Platform.objects.all(),
  351. label='Platform (ID)',
  352. )
  353. platform = django_filters.ModelMultipleChoiceFilter(
  354. name='platform__slug',
  355. queryset=Platform.objects.all(),
  356. to_field_name='slug',
  357. label='Platform (slug)',
  358. )
  359. name = NullableCharFieldFilter()
  360. asset_tag = NullableCharFieldFilter()
  361. site_id = django_filters.ModelMultipleChoiceFilter(
  362. queryset=Site.objects.all(),
  363. label='Site (ID)',
  364. )
  365. site = django_filters.ModelMultipleChoiceFilter(
  366. name='site__slug',
  367. queryset=Site.objects.all(),
  368. to_field_name='slug',
  369. label='Site name (slug)',
  370. )
  371. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  372. name='rack__group',
  373. queryset=RackGroup.objects.all(),
  374. label='Rack group (ID)',
  375. )
  376. rack_id = django_filters.ModelMultipleChoiceFilter(
  377. name='rack',
  378. queryset=Rack.objects.all(),
  379. label='Rack (ID)',
  380. )
  381. cluster_id = django_filters.ModelMultipleChoiceFilter(
  382. queryset=Cluster.objects.all(),
  383. label='VM cluster (ID)',
  384. )
  385. model = django_filters.ModelMultipleChoiceFilter(
  386. name='device_type__slug',
  387. queryset=DeviceType.objects.all(),
  388. to_field_name='slug',
  389. label='Device model (slug)',
  390. )
  391. status = django_filters.MultipleChoiceFilter(
  392. choices=DEVICE_STATUS_CHOICES,
  393. null_value=None
  394. )
  395. is_full_depth = django_filters.BooleanFilter(
  396. name='device_type__is_full_depth',
  397. label='Is full depth',
  398. )
  399. is_console_server = django_filters.BooleanFilter(
  400. name='device_type__is_console_server',
  401. label='Is a console server',
  402. )
  403. is_pdu = django_filters.BooleanFilter(
  404. name='device_type__is_pdu',
  405. label='Is a PDU',
  406. )
  407. is_network_device = django_filters.BooleanFilter(
  408. name='device_type__is_network_device',
  409. label='Is a network device',
  410. )
  411. mac_address = django_filters.CharFilter(
  412. method='_mac_address',
  413. label='MAC address',
  414. )
  415. has_primary_ip = django_filters.BooleanFilter(
  416. method='_has_primary_ip',
  417. label='Has a primary IP',
  418. )
  419. class Meta:
  420. model = Device
  421. fields = ['serial', 'position']
  422. def search(self, queryset, name, value):
  423. if not value.strip():
  424. return queryset
  425. return queryset.filter(
  426. Q(name__icontains=value) |
  427. Q(serial__icontains=value.strip()) |
  428. Q(inventory_items__serial__icontains=value.strip()) |
  429. Q(asset_tag=value.strip()) |
  430. Q(comments__icontains=value)
  431. ).distinct()
  432. def _mac_address(self, queryset, name, value):
  433. value = value.strip()
  434. if not value:
  435. return queryset
  436. try:
  437. mac = EUI(value.strip())
  438. return queryset.filter(interfaces__mac_address=mac).distinct()
  439. except AddrFormatError:
  440. return queryset.none()
  441. def _has_primary_ip(self, queryset, name, value):
  442. if value:
  443. return queryset.filter(
  444. Q(primary_ip4__isnull=False) |
  445. Q(primary_ip6__isnull=False)
  446. )
  447. else:
  448. return queryset.exclude(
  449. Q(primary_ip4__isnull=False) |
  450. Q(primary_ip6__isnull=False)
  451. )
  452. class DeviceComponentFilterSet(django_filters.FilterSet):
  453. device_id = django_filters.ModelChoiceFilter(
  454. queryset=Device.objects.all(),
  455. label='Device (ID)',
  456. )
  457. device = django_filters.ModelChoiceFilter(
  458. queryset=Device.objects.all(),
  459. to_field_name='name',
  460. label='Device (name)',
  461. )
  462. class ConsolePortFilter(DeviceComponentFilterSet):
  463. class Meta:
  464. model = ConsolePort
  465. fields = ['name']
  466. class ConsoleServerPortFilter(DeviceComponentFilterSet):
  467. class Meta:
  468. model = ConsoleServerPort
  469. fields = ['name']
  470. class PowerPortFilter(DeviceComponentFilterSet):
  471. class Meta:
  472. model = PowerPort
  473. fields = ['name']
  474. class PowerOutletFilter(DeviceComponentFilterSet):
  475. class Meta:
  476. model = PowerOutlet
  477. fields = ['name']
  478. class InterfaceFilter(django_filters.FilterSet):
  479. """
  480. Not using DeviceComponentFilterSet for Interfaces because we need to glean the ordering logic from the parent
  481. Device's DeviceType.
  482. """
  483. device = django_filters.CharFilter(
  484. method='filter_device',
  485. name='name',
  486. label='Device',
  487. )
  488. device_id = django_filters.NumberFilter(
  489. method='filter_device',
  490. name='pk',
  491. label='Device (ID)',
  492. )
  493. type = django_filters.CharFilter(
  494. method='filter_type',
  495. label='Interface type',
  496. )
  497. lag_id = django_filters.ModelMultipleChoiceFilter(
  498. name='lag',
  499. queryset=Interface.objects.all(),
  500. label='LAG interface (ID)',
  501. )
  502. mac_address = django_filters.CharFilter(
  503. method='_mac_address',
  504. label='MAC address',
  505. )
  506. class Meta:
  507. model = Interface
  508. fields = ['name', 'form_factor', 'enabled', 'mtu', 'mgmt_only']
  509. def filter_device(self, queryset, name, value):
  510. try:
  511. device = Device.objects.select_related('device_type').get(**{name: value})
  512. vc_interface_ids = [i['id'] for i in device.vc_interfaces.values('id')]
  513. ordering = device.device_type.interface_ordering
  514. return queryset.filter(pk__in=vc_interface_ids).order_naturally(ordering)
  515. except Device.DoesNotExist:
  516. return queryset.none()
  517. def filter_type(self, queryset, name, value):
  518. value = value.strip().lower()
  519. return {
  520. 'physical': queryset.exclude(form_factor__in=NONCONNECTABLE_IFACE_TYPES),
  521. 'virtual': queryset.filter(form_factor__in=VIRTUAL_IFACE_TYPES),
  522. 'wireless': queryset.filter(form_factor__in=WIRELESS_IFACE_TYPES),
  523. 'lag': queryset.filter(form_factor=IFACE_FF_LAG),
  524. }.get(value, queryset.none())
  525. def _mac_address(self, queryset, name, value):
  526. value = value.strip()
  527. if not value:
  528. return queryset
  529. try:
  530. mac = EUI(value.strip())
  531. return queryset.filter(mac_address=mac)
  532. except AddrFormatError:
  533. return queryset.none()
  534. class DeviceBayFilter(DeviceComponentFilterSet):
  535. class Meta:
  536. model = DeviceBay
  537. fields = ['name']
  538. class InventoryItemFilter(DeviceComponentFilterSet):
  539. parent_id = django_filters.ModelMultipleChoiceFilter(
  540. queryset=InventoryItem.objects.all(),
  541. label='Parent inventory item (ID)',
  542. )
  543. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  544. queryset=Manufacturer.objects.all(),
  545. label='Manufacturer (ID)',
  546. )
  547. manufacturer = django_filters.ModelMultipleChoiceFilter(
  548. name='manufacturer__slug',
  549. queryset=Manufacturer.objects.all(),
  550. to_field_name='slug',
  551. label='Manufacturer (slug)',
  552. )
  553. asset_tag = NullableCharFieldFilter()
  554. class Meta:
  555. model = InventoryItem
  556. fields = ['name', 'part_id', 'serial', 'discovered']
  557. class VirtualChassisFilter(django_filters.FilterSet):
  558. class Meta:
  559. model = VirtualChassis
  560. fields = ['domain']
  561. class VCMembershipFilter(django_filters.FilterSet):
  562. class Meta:
  563. model = VCMembership
  564. fields = ['virtual_chassis', 'device', 'position', 'is_master', 'priority']
  565. class ConsoleConnectionFilter(django_filters.FilterSet):
  566. site = django_filters.CharFilter(
  567. method='filter_site',
  568. label='Site (slug)',
  569. )
  570. device = django_filters.CharFilter(
  571. method='filter_device',
  572. label='Device',
  573. )
  574. class Meta:
  575. model = ConsolePort
  576. fields = ['name', 'connection_status']
  577. def filter_site(self, queryset, name, value):
  578. if not value.strip():
  579. return queryset
  580. return queryset.filter(cs_port__device__site__slug=value)
  581. def filter_device(self, queryset, name, value):
  582. if not value.strip():
  583. return queryset
  584. return queryset.filter(
  585. Q(device__name__icontains=value) |
  586. Q(cs_port__device__name__icontains=value)
  587. )
  588. class PowerConnectionFilter(django_filters.FilterSet):
  589. site = django_filters.CharFilter(
  590. method='filter_site',
  591. label='Site (slug)',
  592. )
  593. device = django_filters.CharFilter(
  594. method='filter_device',
  595. label='Device',
  596. )
  597. class Meta:
  598. model = PowerPort
  599. fields = ['name', 'connection_status']
  600. def filter_site(self, queryset, name, value):
  601. if not value.strip():
  602. return queryset
  603. return queryset.filter(power_outlet__device__site__slug=value)
  604. def filter_device(self, queryset, name, value):
  605. if not value.strip():
  606. return queryset
  607. return queryset.filter(
  608. Q(device__name__icontains=value) |
  609. Q(power_outlet__device__name__icontains=value)
  610. )
  611. class InterfaceConnectionFilter(django_filters.FilterSet):
  612. site = django_filters.CharFilter(
  613. method='filter_site',
  614. label='Site (slug)',
  615. )
  616. device = django_filters.CharFilter(
  617. method='filter_device',
  618. label='Device',
  619. )
  620. class Meta:
  621. model = InterfaceConnection
  622. fields = ['connection_status']
  623. def filter_site(self, queryset, name, value):
  624. if not value.strip():
  625. return queryset
  626. return queryset.filter(
  627. Q(interface_a__device__site__slug=value) |
  628. Q(interface_b__device__site__slug=value)
  629. )
  630. def filter_device(self, queryset, name, value):
  631. if not value.strip():
  632. return queryset
  633. return queryset.filter(
  634. Q(interface_a__device__name__icontains=value) |
  635. Q(interface_b__device__name__icontains=value)
  636. )