Further optimizations, improve counting to rely on backend DB

This commit is contained in:
2026-01-18 23:23:16 +01:00
parent 6ab9db4ed4
commit 4dde4225eb
7 changed files with 345 additions and 19 deletions

View File

@@ -194,6 +194,12 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
]
data = []
# Prefetch related data to avoid N+1 queries
queryset = queryset.select_related(
'publisher', 'shop'
).prefetch_related('authors', 'tags', 'property__property')
for obj in queryset:
properties = settings.CSV_SEPARATOR_ALT.join(
"{}:{}".format(property.property.name, property.value)
@@ -360,6 +366,12 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
]
data = []
# Prefetch related data to avoid N+1 queries
queryset = queryset.select_related(
'manufacturer', 'shop'
).prefetch_related('scales', 'tags', 'property__property')
for obj in queryset:
properties = settings.CSV_SEPARATOR_ALT.join(
"{}:{}".format(property.property.name, property.value)

View File

@@ -122,12 +122,27 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin):
"Item ID",
]
data = []
# Prefetch related data to avoid N+1 queries
queryset = queryset.select_related(
'company', 'scale'
).prefetch_related(
'tags',
'consist_item__rolling_stock__rolling_class__type'
)
for obj in queryset:
# Cache the type count to avoid recalculating for each item
types = " + ".join(
"{}x {}".format(t["count"], t["type"])
for t in obj.get_type_count()
)
# Cache tags to avoid repeated queries
tags_str = settings.CSV_SEPARATOR_ALT.join(
t.name for t in obj.tags.all()
)
for item in obj.consist_item.all():
types = " + ".join(
"{}x {}".format(t["count"], t["type"])
for t in obj.get_type_count()
)
data.append(
[
obj.uuid,
@@ -139,9 +154,7 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin):
obj.scale.scale,
obj.era,
html.unescape(strip_tags(obj.description)),
settings.CSV_SEPARATOR_ALT.join(
t.name for t in obj.tags.all()
),
tags_str,
obj.length,
types,
item.rolling_stock.__str__(),

View File

@@ -48,6 +48,11 @@ class Consist(BaseModel):
def length(self):
return self.consist_item.filter(load=False).count()
@property
def loads_count(self):
"""Count of loads in this consist using database aggregation."""
return self.consist_item.filter(load=True).count()
def get_type_count(self):
return self.consist_item.filter(load=False).annotate(
type=models.F("rolling_stock__rolling_class__type__type")

View File

@@ -142,7 +142,7 @@
</tr>
<tr>
<th scope="row">Composition</th>
<td>{% for t in consist.get_type_count %}{{ t.count }}x {{ t.type }} {{t.category }}{% if not forloop.last %} &raquo; {% endif %}{% endfor %}{% if loads %} | <i class="bi bi-download"></i> {{ loads|length }}x Load{{ loads|pluralize }}{% endif %}</td>
<td>{% for t in consist.get_type_count %}{{ t.count }}x {{ t.type }} {{t.category }}{% if not forloop.last %} &raquo; {% endif %}{% endfor %}{% if loads %} | <i class="bi bi-download"></i> {{ loads_count }}x Load{{ loads|pluralize }}{% endif %}</td>
</tr>
</tbody>
</table>

View File

@@ -579,6 +579,12 @@ class GetConsist(View):
except ObjectDoesNotExist:
raise Http404
# Get all published rolling stock IDs for efficient filtering
published_ids = set(
RollingStock.objects.get_published(request.user)
.values_list('uuid', flat=True)
)
# Fetch consist items with related rolling stock in one query
consist_items = consist.consist_item.select_related(
'rolling_stock',
@@ -589,21 +595,17 @@ class GetConsist(View):
'rolling_stock__scale',
).prefetch_related('rolling_stock__image')
# Filter items and loads
data = list(
# Filter items and loads efficiently
data = [
item.rolling_stock
for item in consist_items.filter(load=False)
if RollingStock.objects.get_published(request.user)
.filter(uuid=item.rolling_stock_id)
.exists()
)
loads = list(
if item.rolling_stock.uuid in published_ids
]
loads = [
item.rolling_stock
for item in consist_items.filter(load=True)
if RollingStock.objects.get_published(request.user)
.filter(uuid=item.rolling_stock_id)
.exists()
)
if item.rolling_stock.uuid in published_ids
]
paginator = Paginator(data, get_items_per_page())
data = paginator.get_page(page)
@@ -619,6 +621,7 @@ class GetConsist(View):
"consist": consist,
"data": data,
"loads": loads,
"loads_count": len(loads),
"page_range": page_range,
},
)

View File

@@ -273,6 +273,18 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
"Properties",
]
data = []
# Prefetch related data to avoid N+1 queries
queryset = queryset.select_related(
'rolling_class',
'rolling_class__type',
'rolling_class__company',
'manufacturer',
'scale',
'decoder',
'shop'
).prefetch_related('tags', 'property__property')
for obj in queryset:
properties = settings.CSV_SEPARATOR_ALT.join(
"{}:{}".format(property.property.name, property.value)