filters.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.db.models import Q
  5. from django.forms import DateField, IntegerField, NullBooleanField
  6. from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup
  7. from tenancy.models import Tenant, TenantGroup
  8. from utilities.filters import BaseFilterSet, ContentTypeFilter
  9. from virtualization.models import Cluster, ClusterGroup
  10. from .choices import *
  11. from .models import *
  12. __all__ = (
  13. 'ConfigContextFilterSet',
  14. 'ContentTypeFilterSet',
  15. 'CreatedUpdatedFilterSet',
  16. 'CustomFieldFilter',
  17. 'CustomLinkFilterSet',
  18. 'CustomFieldModelFilterSet',
  19. 'ExportTemplateFilterSet',
  20. 'ImageAttachmentFilterSet',
  21. 'JournalEntryFilterSet',
  22. 'LocalConfigContextFilterSet',
  23. 'ObjectChangeFilterSet',
  24. 'TagFilterSet',
  25. 'WebhookFilterSet',
  26. )
  27. EXACT_FILTER_TYPES = (
  28. CustomFieldTypeChoices.TYPE_BOOLEAN,
  29. CustomFieldTypeChoices.TYPE_DATE,
  30. CustomFieldTypeChoices.TYPE_INTEGER,
  31. CustomFieldTypeChoices.TYPE_SELECT,
  32. )
  33. class WebhookFilterSet(BaseFilterSet):
  34. content_types = ContentTypeFilter()
  35. http_method = django_filters.MultipleChoiceFilter(
  36. choices=WebhookHttpMethodChoices
  37. )
  38. class Meta:
  39. model = Webhook
  40. fields = [
  41. 'id', 'content_types', 'name', 'type_create', 'type_update', 'type_delete', 'payload_url', 'enabled',
  42. 'http_method', 'http_content_type', 'secret', 'ssl_verification', 'ca_file_path',
  43. ]
  44. class CustomFieldFilter(django_filters.Filter):
  45. """
  46. Filter objects by the presence of a CustomFieldValue. The filter's name is used as the CustomField name.
  47. """
  48. def __init__(self, custom_field, *args, **kwargs):
  49. self.custom_field = custom_field
  50. if custom_field.type == CustomFieldTypeChoices.TYPE_INTEGER:
  51. self.field_class = IntegerField
  52. elif custom_field.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
  53. self.field_class = NullBooleanField
  54. elif custom_field.type == CustomFieldTypeChoices.TYPE_DATE:
  55. self.field_class = DateField
  56. super().__init__(*args, **kwargs)
  57. self.field_name = f'custom_field_data__{self.field_name}'
  58. if custom_field.type not in EXACT_FILTER_TYPES:
  59. if custom_field.filter_logic == CustomFieldFilterLogicChoices.FILTER_LOOSE:
  60. self.lookup_expr = 'icontains'
  61. class CustomFieldModelFilterSet(django_filters.FilterSet):
  62. """
  63. Dynamically add a Filter for each CustomField applicable to the parent model.
  64. """
  65. def __init__(self, *args, **kwargs):
  66. super().__init__(*args, **kwargs)
  67. custom_fields = CustomField.objects.filter(
  68. content_types=ContentType.objects.get_for_model(self._meta.model)
  69. ).exclude(
  70. filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED
  71. )
  72. for cf in custom_fields:
  73. self.filters['cf_{}'.format(cf.name)] = CustomFieldFilter(field_name=cf.name, custom_field=cf)
  74. class CustomFieldFilterSet(django_filters.FilterSet):
  75. class Meta:
  76. model = CustomField
  77. fields = ['id', 'content_types', 'name', 'required', 'filter_logic', 'weight']
  78. class CustomLinkFilterSet(BaseFilterSet):
  79. class Meta:
  80. model = CustomLink
  81. fields = ['id', 'content_type', 'name', 'link_text', 'link_url', 'weight', 'group_name', 'new_window']
  82. class ExportTemplateFilterSet(BaseFilterSet):
  83. class Meta:
  84. model = ExportTemplate
  85. fields = ['id', 'content_type', 'name']
  86. class ImageAttachmentFilterSet(BaseFilterSet):
  87. content_type = ContentTypeFilter()
  88. class Meta:
  89. model = ImageAttachment
  90. fields = ['id', 'content_type_id', 'object_id', 'name']
  91. class JournalEntryFilterSet(BaseFilterSet):
  92. q = django_filters.CharFilter(
  93. method='search',
  94. label='Search',
  95. )
  96. created = django_filters.DateTimeFromToRangeFilter()
  97. assigned_object_type = ContentTypeFilter()
  98. created_by_id = django_filters.ModelMultipleChoiceFilter(
  99. queryset=User.objects.all(),
  100. label='User (ID)',
  101. )
  102. created_by = django_filters.ModelMultipleChoiceFilter(
  103. field_name='created_by__username',
  104. queryset=User.objects.all(),
  105. to_field_name='username',
  106. label='User (name)',
  107. )
  108. kind = django_filters.MultipleChoiceFilter(
  109. choices=JournalEntryKindChoices
  110. )
  111. class Meta:
  112. model = JournalEntry
  113. fields = ['id', 'assigned_object_type_id', 'assigned_object_id', 'created', 'kind']
  114. def search(self, queryset, name, value):
  115. if not value.strip():
  116. return queryset
  117. return queryset.filter(comments__icontains=value)
  118. class TagFilterSet(BaseFilterSet):
  119. q = django_filters.CharFilter(
  120. method='search',
  121. label='Search',
  122. )
  123. class Meta:
  124. model = Tag
  125. fields = ['id', 'name', 'slug', 'color']
  126. def search(self, queryset, name, value):
  127. if not value.strip():
  128. return queryset
  129. return queryset.filter(
  130. Q(name__icontains=value) |
  131. Q(slug__icontains=value)
  132. )
  133. class ConfigContextFilterSet(BaseFilterSet):
  134. q = django_filters.CharFilter(
  135. method='search',
  136. label='Search',
  137. )
  138. region_id = django_filters.ModelMultipleChoiceFilter(
  139. field_name='regions',
  140. queryset=Region.objects.all(),
  141. label='Region',
  142. )
  143. region = django_filters.ModelMultipleChoiceFilter(
  144. field_name='regions__slug',
  145. queryset=Region.objects.all(),
  146. to_field_name='slug',
  147. label='Region (slug)',
  148. )
  149. site_group = django_filters.ModelMultipleChoiceFilter(
  150. field_name='site_groups__slug',
  151. queryset=SiteGroup.objects.all(),
  152. to_field_name='slug',
  153. label='Site group (slug)',
  154. )
  155. site_group_id = django_filters.ModelMultipleChoiceFilter(
  156. field_name='site_groups',
  157. queryset=SiteGroup.objects.all(),
  158. label='Site group',
  159. )
  160. site_id = django_filters.ModelMultipleChoiceFilter(
  161. field_name='sites',
  162. queryset=Site.objects.all(),
  163. label='Site',
  164. )
  165. site = django_filters.ModelMultipleChoiceFilter(
  166. field_name='sites__slug',
  167. queryset=Site.objects.all(),
  168. to_field_name='slug',
  169. label='Site (slug)',
  170. )
  171. device_type_id = django_filters.ModelMultipleChoiceFilter(
  172. field_name='device_types',
  173. queryset=DeviceType.objects.all(),
  174. label='Device type',
  175. )
  176. role_id = django_filters.ModelMultipleChoiceFilter(
  177. field_name='roles',
  178. queryset=DeviceRole.objects.all(),
  179. label='Role',
  180. )
  181. role = django_filters.ModelMultipleChoiceFilter(
  182. field_name='roles__slug',
  183. queryset=DeviceRole.objects.all(),
  184. to_field_name='slug',
  185. label='Role (slug)',
  186. )
  187. platform_id = django_filters.ModelMultipleChoiceFilter(
  188. field_name='platforms',
  189. queryset=Platform.objects.all(),
  190. label='Platform',
  191. )
  192. platform = django_filters.ModelMultipleChoiceFilter(
  193. field_name='platforms__slug',
  194. queryset=Platform.objects.all(),
  195. to_field_name='slug',
  196. label='Platform (slug)',
  197. )
  198. cluster_group_id = django_filters.ModelMultipleChoiceFilter(
  199. field_name='cluster_groups',
  200. queryset=ClusterGroup.objects.all(),
  201. label='Cluster group',
  202. )
  203. cluster_group = django_filters.ModelMultipleChoiceFilter(
  204. field_name='cluster_groups__slug',
  205. queryset=ClusterGroup.objects.all(),
  206. to_field_name='slug',
  207. label='Cluster group (slug)',
  208. )
  209. cluster_id = django_filters.ModelMultipleChoiceFilter(
  210. field_name='clusters',
  211. queryset=Cluster.objects.all(),
  212. label='Cluster',
  213. )
  214. tenant_group_id = django_filters.ModelMultipleChoiceFilter(
  215. field_name='tenant_groups',
  216. queryset=TenantGroup.objects.all(),
  217. label='Tenant group',
  218. )
  219. tenant_group = django_filters.ModelMultipleChoiceFilter(
  220. field_name='tenant_groups__slug',
  221. queryset=TenantGroup.objects.all(),
  222. to_field_name='slug',
  223. label='Tenant group (slug)',
  224. )
  225. tenant_id = django_filters.ModelMultipleChoiceFilter(
  226. field_name='tenants',
  227. queryset=Tenant.objects.all(),
  228. label='Tenant',
  229. )
  230. tenant = django_filters.ModelMultipleChoiceFilter(
  231. field_name='tenants__slug',
  232. queryset=Tenant.objects.all(),
  233. to_field_name='slug',
  234. label='Tenant (slug)',
  235. )
  236. tag = django_filters.ModelMultipleChoiceFilter(
  237. field_name='tags__slug',
  238. queryset=Tag.objects.all(),
  239. to_field_name='slug',
  240. label='Tag (slug)',
  241. )
  242. class Meta:
  243. model = ConfigContext
  244. fields = ['id', 'name', 'is_active']
  245. def search(self, queryset, name, value):
  246. if not value.strip():
  247. return queryset
  248. return queryset.filter(
  249. Q(name__icontains=value) |
  250. Q(description__icontains=value) |
  251. Q(data__icontains=value)
  252. )
  253. #
  254. # Filter for Local Config Context Data
  255. #
  256. class LocalConfigContextFilterSet(django_filters.FilterSet):
  257. local_context_data = django_filters.BooleanFilter(
  258. method='_local_context_data',
  259. label='Has local config context data',
  260. )
  261. def _local_context_data(self, queryset, name, value):
  262. return queryset.exclude(local_context_data__isnull=value)
  263. class ObjectChangeFilterSet(BaseFilterSet):
  264. q = django_filters.CharFilter(
  265. method='search',
  266. label='Search',
  267. )
  268. time = django_filters.DateTimeFromToRangeFilter()
  269. changed_object_type = ContentTypeFilter()
  270. user_id = django_filters.ModelMultipleChoiceFilter(
  271. queryset=User.objects.all(),
  272. label='User (ID)',
  273. )
  274. user = django_filters.ModelMultipleChoiceFilter(
  275. field_name='user__username',
  276. queryset=User.objects.all(),
  277. to_field_name='username',
  278. label='User name',
  279. )
  280. class Meta:
  281. model = ObjectChange
  282. fields = [
  283. 'id', 'user', 'user_name', 'request_id', 'action', 'changed_object_type_id', 'changed_object_id',
  284. 'object_repr',
  285. ]
  286. def search(self, queryset, name, value):
  287. if not value.strip():
  288. return queryset
  289. return queryset.filter(
  290. Q(user_name__icontains=value) |
  291. Q(object_repr__icontains=value)
  292. )
  293. class CreatedUpdatedFilterSet(django_filters.FilterSet):
  294. created = django_filters.DateFilter()
  295. created__gte = django_filters.DateFilter(
  296. field_name='created',
  297. lookup_expr='gte'
  298. )
  299. created__lte = django_filters.DateFilter(
  300. field_name='created',
  301. lookup_expr='lte'
  302. )
  303. last_updated = django_filters.DateTimeFilter()
  304. last_updated__gte = django_filters.DateTimeFilter(
  305. field_name='last_updated',
  306. lookup_expr='gte'
  307. )
  308. last_updated__lte = django_filters.DateTimeFilter(
  309. field_name='last_updated',
  310. lookup_expr='lte'
  311. )
  312. #
  313. # Job Results
  314. #
  315. class JobResultFilterSet(BaseFilterSet):
  316. q = django_filters.CharFilter(
  317. method='search',
  318. label='Search',
  319. )
  320. created = django_filters.DateTimeFilter()
  321. completed = django_filters.DateTimeFilter()
  322. status = django_filters.MultipleChoiceFilter(
  323. choices=JobResultStatusChoices,
  324. null_value=None
  325. )
  326. class Meta:
  327. model = JobResult
  328. fields = [
  329. 'id', 'created', 'completed', 'status', 'user', 'obj_type', 'name'
  330. ]
  331. def search(self, queryset, name, value):
  332. if not value.strip():
  333. return queryset
  334. return queryset.filter(
  335. Q(user__username__icontains=value)
  336. )
  337. #
  338. # ContentTypes
  339. #
  340. class ContentTypeFilterSet(django_filters.FilterSet):
  341. class Meta:
  342. model = ContentType
  343. fields = ['id', 'app_label', 'model']