From e83b3bca199f83ed3990b7e5fecbc12620e49184 Mon Sep 17 00:00:00 2001 From: arcstur Date: Fri, 13 Mar 2026 23:17:46 -0300 Subject: [PATCH 1/3] refactor: greatly improves home page performance by prefetching Tags instead of letting N+1 queries --- store/models.py | 3 ++- store/views.py | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/store/models.py b/store/models.py index e866572..0866196 100644 --- a/store/models.py +++ b/store/models.py @@ -207,7 +207,8 @@ def tag_ids(self): @cached_property def sorted_tags(self): - return self.tags.order_by('-priority', 'id') + # tags will come sorted through view queryset + return self.tags.all() @cached_property def reverting_batches(self): diff --git a/store/views.py b/store/views.py index 54f90d1..59826ee 100644 --- a/store/views.py +++ b/store/views.py @@ -1,4 +1,5 @@ from django.shortcuts import render +from django.db.models import Prefetch from django.http import Http404 from rest_framework import viewsets @@ -14,6 +15,7 @@ from .serializers import BatchSimpleSerializer, BatchDetailSerializer, BatchCSVSerializer, EditSerializer, ToolSerializer, ToolStatsSerializer from django_filters.rest_framework import DjangoFilterBackend from tagging.filters import TaggingFilterBackend +from tagging.models import Tag class BatchView(generics.RetrieveAPIView): serializer_class = BatchDetailSerializer @@ -46,7 +48,17 @@ class APIBatchView(BatchView): class BatchesView(generics.ListAPIView): serializer_class = BatchSimpleSerializer - queryset = Batch.objects.all().order_by('-ended') + queryset = ( + Batch.objects + .select_related('tool') + .prefetch_related( + Prefetch( + 'tags', + queryset=Tag.objects.order_by('-priority', 'id'), + ) + ) + .order_by('-ended') + ) template_name = 'store/batches.html' filter_fields = ('user',) filter_backends = (TaggingFilterBackend,) From b811ab8329d5fd50cd8416782174369e2c6dc845 Mon Sep 17 00:00:00 2001 From: arcstur Date: Fri, 13 Mar 2026 23:20:35 -0300 Subject: [PATCH 2/3] refactor: move ordering to Tag's Meta --- store/models.py | 2 +- store/views.py | 8 +------- tagging/models.py | 3 +++ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/store/models.py b/store/models.py index 0866196..42d9aa6 100644 --- a/store/models.py +++ b/store/models.py @@ -207,7 +207,7 @@ def tag_ids(self): @cached_property def sorted_tags(self): - # tags will come sorted through view queryset + # tags come sorted through its Meta ordering return self.tags.all() @cached_property diff --git a/store/views.py b/store/views.py index 59826ee..c4a960c 100644 --- a/store/views.py +++ b/store/views.py @@ -1,5 +1,4 @@ from django.shortcuts import render -from django.db.models import Prefetch from django.http import Http404 from rest_framework import viewsets @@ -51,12 +50,7 @@ class BatchesView(generics.ListAPIView): queryset = ( Batch.objects .select_related('tool') - .prefetch_related( - Prefetch( - 'tags', - queryset=Tag.objects.order_by('-priority', 'id'), - ) - ) + .prefetch_related('tags') .order_by('-ended') ) template_name = 'store/batches.html' diff --git a/tagging/models.py b/tagging/models.py index 30085c0..8d3a1f5 100644 --- a/tagging/models.py +++ b/tagging/models.py @@ -130,6 +130,9 @@ class Tag(CachingMixin, models.Model): #: Color for the tag (HTML coded, including hash) color = models.CharField(max_length=32, default='#939393') + class Meta: + ordering = ['-priority', 'id'] + @property def display_name(self): """ From 9495219246d9b3c479e45c004bdbd2e86801ce5b Mon Sep 17 00:00:00 2001 From: arcstur Date: Fri, 13 Mar 2026 23:24:29 -0300 Subject: [PATCH 3/3] build: migrations --- revert/migrations/0002_alter_reverttask_id.py | 18 +++++++++++++++ .../0024_alter_batch_id_alter_tool_id.py | 23 +++++++++++++++++++ tagging/migrations/0006_alter_tag_options.py | 17 ++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 revert/migrations/0002_alter_reverttask_id.py create mode 100644 store/migrations/0024_alter_batch_id_alter_tool_id.py create mode 100644 tagging/migrations/0006_alter_tag_options.py diff --git a/revert/migrations/0002_alter_reverttask_id.py b/revert/migrations/0002_alter_reverttask_id.py new file mode 100644 index 0000000..a628bca --- /dev/null +++ b/revert/migrations/0002_alter_reverttask_id.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2026-03-14 02:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('revert', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='reverttask', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/store/migrations/0024_alter_batch_id_alter_tool_id.py b/store/migrations/0024_alter_batch_id_alter_tool_id.py new file mode 100644 index 0000000..339be45 --- /dev/null +++ b/store/migrations/0024_alter_batch_id_alter_tool_id.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.7 on 2026-03-14 02:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('store', '0023_edits_bigints'), + ] + + operations = [ + migrations.AlterField( + model_name='batch', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='tool', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/tagging/migrations/0006_alter_tag_options.py b/tagging/migrations/0006_alter_tag_options.py new file mode 100644 index 0000000..5af12c3 --- /dev/null +++ b/tagging/migrations/0006_alter_tag_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.7 on 2026-03-14 02:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tagging', '0005_inspect_batches'), + ] + + operations = [ + migrations.AlterModelOptions( + name='tag', + options={'ordering': ['-priority', 'id']}, + ), + ]