Skip to content

Commit 46f4a12

Browse files
committed
[fix] Fixed sorting issue in templates
Using the 'sort_value' of the 'through_model', created a subquery which annotates a sort_value and selected field to each template. The sort_value is used for ordering the templates and also for checking if template is selected or not using a large default value which happens if template is not selected for a device config or group. Signed-off-by: DragnEmperor <[email protected]>
1 parent f0bb030 commit 46f4a12

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

openwisp_controller/config/views.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
from copy import deepcopy
33
from uuid import UUID
44

5+
from django.db import models as django_models
56
from django.db.models import Q
7+
from django.db.models.functions import Coalesce
68
from django.http import HttpResponse, JsonResponse
79
from django.utils import timezone
810
from django.utils.module_loading import import_string
@@ -31,34 +33,58 @@ def get_relevant_templates(request, organization_id):
3133
if not user.is_superuser and not user.is_manager(organization_id):
3234
return HttpResponse(status=403)
3335
org = get_object_or_404(Organization, pk=organization_id, is_active=True)
36+
org_filters = Q(organization_id=org.pk) | Q(organization_id=None)
3437
filter_options = {}
3538
if backend:
3639
filter_options.update(backend=backend)
3740
else:
3841
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
3965
queryset = (
4066
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')
4277
.only('id', 'name', 'backend', 'default', 'required')
4378
)
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+
5480
relevant_templates = {}
5581
for template in queryset:
5682
relevant_templates[str(template.pk)] = dict(
5783
name=template.name,
5884
backend=template.get_backend_display(),
5985
default=template.default,
6086
required=template.required,
61-
selected=template.pk in selected_templates,
87+
selected=template.selected,
6288
)
6389
return JsonResponse(relevant_templates)
6490

0 commit comments

Comments
 (0)