|
2 | 2 | from copy import deepcopy |
3 | 3 | from uuid import UUID |
4 | 4 |
|
| 5 | +from django.db import models as django_models |
5 | 6 | from django.db.models import Q |
| 7 | +from django.db.models.functions import Coalesce |
6 | 8 | from django.http import HttpResponse, JsonResponse |
7 | 9 | from django.utils import timezone |
8 | 10 | from django.utils.module_loading import import_string |
@@ -31,34 +33,58 @@ def get_relevant_templates(request, organization_id): |
31 | 33 | if not user.is_superuser and not user.is_manager(organization_id): |
32 | 34 | return HttpResponse(status=403) |
33 | 35 | org = get_object_or_404(Organization, pk=organization_id, is_active=True) |
| 36 | + org_filters = Q(organization_id=org.pk) | Q(organization_id=None) |
34 | 37 | filter_options = {} |
35 | 38 | if backend: |
36 | 39 | filter_options.update(backend=backend) |
37 | 40 | else: |
38 | 41 | filter_options.update(required=False, default=False) |
| 42 | + sort_value_subquery = None |
| 43 | + # fetch the selected templates for the device or group by creating a subquery. |
| 44 | + # through_model and lookup_field are set based on the presence of device_id or |
| 45 | + # group_id. we need through_model as `sort_value` is a field of the through model. |
| 46 | + # the subquery will be used to annotate the queryset with the sort_value |
| 47 | + # of the selected templates. |
| 48 | + if device_id and (lookup := Config.objects.filter(device_id=device_id).first()): |
| 49 | + through_model = Config.templates.through |
| 50 | + lookup_field = "config_id" |
| 51 | + if group_id and ( |
| 52 | + lookup := DeviceGroup.objects.filter(Q(pk=group_id) & (org_filters)).first() |
| 53 | + ): |
| 54 | + through_model = DeviceGroup.templates.through |
| 55 | + lookup_field = "devicegroup_id" |
| 56 | + if device_id or group_id: |
| 57 | + sort_value_subquery = django_models.Subquery( |
| 58 | + through_model.objects.filter( |
| 59 | + **{lookup_field: lookup.id}, template_id=django_models.OuterRef('pk') |
| 60 | + ).values('sort_value')[:1], |
| 61 | + output_field=django_models.IntegerField(), |
| 62 | + ) |
| 63 | + # annotated a selected field which is True based on sort_value |
| 64 | + # if sort_value is 9999 then selected is False else True |
39 | 65 | queryset = ( |
40 | 66 | Template.objects.filter(**filter_options) |
41 | | - .filter(Q(organization_id=org.pk) | Q(organization_id=None)) |
| 67 | + .filter(org_filters) |
| 68 | + .annotate( |
| 69 | + sort_value=Coalesce(sort_value_subquery, django_models.Value(9999)), |
| 70 | + selected=django_models.Case( |
| 71 | + django_models.When(sort_value=9999, then=django_models.Value(False)), |
| 72 | + default=django_models.Value(True), |
| 73 | + output_field=django_models.BooleanField(), |
| 74 | + ), |
| 75 | + ) |
| 76 | + .order_by('sort_value') |
42 | 77 | .only('id', 'name', 'backend', 'default', 'required') |
43 | 78 | ) |
44 | | - # for checking which templates are enabled for given device or group |
45 | | - selected_templates = [] |
46 | | - if device_id: |
47 | | - selected_templates = Config.objects.filter(device_id=device_id).values_list( |
48 | | - 'templates__id', flat=True |
49 | | - ) |
50 | | - if group_id: |
51 | | - selected_templates = DeviceGroup.objects.filter( |
52 | | - pk=group_id, organization_id=organization_id |
53 | | - ).values_list('templates__id', flat=True) |
| 79 | + |
54 | 80 | relevant_templates = {} |
55 | 81 | for template in queryset: |
56 | 82 | relevant_templates[str(template.pk)] = dict( |
57 | 83 | name=template.name, |
58 | 84 | backend=template.get_backend_display(), |
59 | 85 | default=template.default, |
60 | 86 | required=template.required, |
61 | | - selected=template.pk in selected_templates, |
| 87 | + selected=template.selected, |
62 | 88 | ) |
63 | 89 | return JsonResponse(relevant_templates) |
64 | 90 |
|
|
0 commit comments