2
0

filters.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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. content_types = ContentTypeFilter()
  76. class Meta:
  77. model = CustomField
  78. fields = ['id', 'content_types', 'name', 'required', 'filter_logic', 'weight']
  79. class CustomLinkFilterSet(BaseFilterSet):
  80. class Meta:
  81. model = CustomLink
  82. fields = ['id', 'content_type', 'name', 'link_text', 'link_url', 'weight', 'group_name', 'new_window']
  83. class ExportTemplateFilterSet(BaseFilterSet):
  84. class Meta:
  85. model = ExportTemplate
  86. fields = ['id', 'content_type', 'name']
  87. class ImageAttachmentFilterSet(BaseFilterSet):
  88. content_type = ContentTypeFilter()
  89. class Meta:
  90. model = ImageAttachment
  91. fields = ['id', 'content_type_id', 'object_id', 'name']
  92. class JournalEntryFilterSet(BaseFilterSet):
  93. q = django_filters.CharFilter(
  94. method='search',
  95. label='Search',
  96. )
  97. created = django_filters.DateTimeFromToRangeFilter()
  98. assigned_object_type = ContentTypeFilter()
  99. created_by_id = django_filters.ModelMultipleChoiceFilter(
  100. queryset=User.objects.all(),
  101. label='User (ID)',
  102. )
  103. created_by = django_filters.ModelMultipleChoiceFilter(
  104. field_name='created_by__username',
  105. queryset=User.objects.all(),
  106. to_field_name='username',
  107. label='User (name)',
  108. )
  109. kind = django_filters.MultipleChoiceFilter(
  110. choices=JournalEntryKindChoices
  111. )
  112. class Meta:
  113. model = JournalEntry
  114. fields = ['id', 'assigned_object_type_id', 'assigned_object_id', 'created', 'kind']
  115. def search(self, queryset, name, value):
  116. if not value.strip():
  117. return queryset
  118. return queryset.filter(comments__icontains=value)
  119. class TagFilterSet(BaseFilterSet):
  120. q = django_filters.CharFilter(
  121. method='search',
  122. label='Search',
  123. )
  124. class Meta:
  125. model = Tag
  126. fields = ['id', 'name', 'slug', 'color']
  127. def search(self, queryset, name, value):
  128. if not value.strip():
  129. return queryset
  130. return queryset.filter(
  131. Q(name__icontains=value) |
  132. Q(slug__icontains=value)
  133. )
  134. class ConfigContextFilterSet(BaseFilterSet):
  135. q = django_filters.CharFilter(
  136. method='search',
  137. label='Search',
  138. )
  139. region_id = django_filters.ModelMultipleChoiceFilter(
  140. field_name='regions',
  141. queryset=Region.objects.all(),
  142. label='Region',
  143. )
  144. region = django_filters.ModelMultipleChoiceFilter(
  145. field_name='regions__slug',
  146. queryset=Region.objects.all(),
  147. to_field_name='slug',
  148. label='Region (slug)',
  149. )
  150. site_group = django_filters.ModelMultipleChoiceFilter(
  151. field_name='site_groups__slug',
  152. queryset=SiteGroup.objects.all(),
  153. to_field_name='slug',
  154. label='Site group (slug)',
  155. )
  156. site_group_id = django_filters.ModelMultipleChoiceFilter(
  157. field_name='site_groups',
  158. queryset=SiteGroup.objects.all(),
  159. label='Site group',
  160. )
  161. site_id = django_filters.ModelMultipleChoiceFilter(
  162. field_name='sites',
  163. queryset=Site.objects.all(),
  164. label='Site',
  165. )
  166. site = django_filters.ModelMultipleChoiceFilter(
  167. field_name='sites__slug',
  168. queryset=Site.objects.all(),
  169. to_field_name='slug',
  170. label='Site (slug)',
  171. )
  172. device_type_id = django_filters.ModelMultipleChoiceFilter(
  173. field_name='device_types',
  174. queryset=DeviceType.objects.all(),
  175. label='Device type',
  176. )
  177. role_id = django_filters.ModelMultipleChoiceFilter(
  178. field_name='roles',
  179. queryset=DeviceRole.objects.all(),
  180. label='Role',
  181. )
  182. role = django_filters.ModelMultipleChoiceFilter(
  183. field_name='roles__slug',
  184. queryset=DeviceRole.objects.all(),
  185. to_field_name='slug',
  186. label='Role (slug)',
  187. )
  188. platform_id = django_filters.ModelMultipleChoiceFilter(
  189. field_name='platforms',
  190. queryset=Platform.objects.all(),
  191. label='Platform',
  192. )
  193. platform = django_filters.ModelMultipleChoiceFilter(
  194. field_name='platforms__slug',
  195. queryset=Platform.objects.all(),
  196. to_field_name='slug',
  197. label='Platform (slug)',
  198. )
  199. cluster_group_id = django_filters.ModelMultipleChoiceFilter(
  200. field_name='cluster_groups',
  201. queryset=ClusterGroup.objects.all(),
  202. label='Cluster group',
  203. )
  204. cluster_group = django_filters.ModelMultipleChoiceFilter(
  205. field_name='cluster_groups__slug',
  206. queryset=ClusterGroup.objects.all(),
  207. to_field_name='slug',
  208. label='Cluster group (slug)',
  209. )
  210. cluster_id = django_filters.ModelMultipleChoiceFilter(
  211. field_name='clusters',
  212. queryset=Cluster.objects.all(),
  213. label='Cluster',
  214. )
  215. tenant_group_id = django_filters.ModelMultipleChoiceFilter(
  216. field_name='tenant_groups',
  217. queryset=TenantGroup.objects.all(),
  218. label='Tenant group',
  219. )
  220. tenant_group = django_filters.ModelMultipleChoiceFilter(
  221. field_name='tenant_groups__slug',
  222. queryset=TenantGroup.objects.all(),
  223. to_field_name='slug',
  224. label='Tenant group (slug)',
  225. )
  226. tenant_id = django_filters.ModelMultipleChoiceFilter(
  227. field_name='tenants',
  228. queryset=Tenant.objects.all(),
  229. label='Tenant',
  230. )
  231. tenant = django_filters.ModelMultipleChoiceFilter(
  232. field_name='tenants__slug',
  233. queryset=Tenant.objects.all(),
  234. to_field_name='slug',
  235. label='Tenant (slug)',
  236. )
  237. tag = django_filters.ModelMultipleChoiceFilter(
  238. field_name='tags__slug',
  239. queryset=Tag.objects.all(),
  240. to_field_name='slug',
  241. label='Tag (slug)',
  242. )
  243. class Meta:
  244. model = ConfigContext
  245. fields = ['id', 'name', 'is_active']
  246. def search(self, queryset, name, value):
  247. if not value.strip():
  248. return queryset
  249. return queryset.filter(
  250. Q(name__icontains=value) |
  251. Q(description__icontains=value) |
  252. Q(data__icontains=value)
  253. )
  254. #
  255. # Filter for Local Config Context Data
  256. #
  257. class LocalConfigContextFilterSet(django_filters.FilterSet):
  258. local_context_data = django_filters.BooleanFilter(
  259. method='_local_context_data',
  260. label='Has local config context data',
  261. )
  262. def _local_context_data(self, queryset, name, value):
  263. return queryset.exclude(local_context_data__isnull=value)
  264. class ObjectChangeFilterSet(BaseFilterSet):
  265. q = django_filters.CharFilter(
  266. method='search',
  267. label='Search',
  268. )
  269. time = django_filters.DateTimeFromToRangeFilter()
  270. changed_object_type = ContentTypeFilter()
  271. user_id = django_filters.ModelMultipleChoiceFilter(
  272. queryset=User.objects.all(),
  273. label='User (ID)',
  274. )
  275. user = django_filters.ModelMultipleChoiceFilter(
  276. field_name='user__username',
  277. queryset=User.objects.all(),
  278. to_field_name='username',
  279. label='User name',
  280. )
  281. class Meta:
  282. model = ObjectChange
  283. fields = [
  284. 'id', 'user', 'user_name', 'request_id', 'action', 'changed_object_type_id', 'changed_object_id',
  285. 'object_repr',
  286. ]
  287. def search(self, queryset, name, value):
  288. if not value.strip():
  289. return queryset
  290. return queryset.filter(
  291. Q(user_name__icontains=value) |
  292. Q(object_repr__icontains=value)
  293. )
  294. class CreatedUpdatedFilterSet(django_filters.FilterSet):
  295. created = django_filters.DateFilter()
  296. created__gte = django_filters.DateFilter(
  297. field_name='created',
  298. lookup_expr='gte'
  299. )
  300. created__lte = django_filters.DateFilter(
  301. field_name='created',
  302. lookup_expr='lte'
  303. )
  304. last_updated = django_filters.DateTimeFilter()
  305. last_updated__gte = django_filters.DateTimeFilter(
  306. field_name='last_updated',
  307. lookup_expr='gte'
  308. )
  309. last_updated__lte = django_filters.DateTimeFilter(
  310. field_name='last_updated',
  311. lookup_expr='lte'
  312. )
  313. #
  314. # Job Results
  315. #
  316. class JobResultFilterSet(BaseFilterSet):
  317. q = django_filters.CharFilter(
  318. method='search',
  319. label='Search',
  320. )
  321. created = django_filters.DateTimeFilter()
  322. completed = django_filters.DateTimeFilter()
  323. status = django_filters.MultipleChoiceFilter(
  324. choices=JobResultStatusChoices,
  325. null_value=None
  326. )
  327. class Meta:
  328. model = JobResult
  329. fields = [
  330. 'id', 'created', 'completed', 'status', 'user', 'obj_type', 'name'
  331. ]
  332. def search(self, queryset, name, value):
  333. if not value.strip():
  334. return queryset
  335. return queryset.filter(
  336. Q(user__username__icontains=value)
  337. )
  338. #
  339. # ContentTypes
  340. #
  341. class ContentTypeFilterSet(django_filters.FilterSet):
  342. class Meta:
  343. model = ContentType
  344. fields = ['id', 'app_label', 'model']