mirror of
https://github.com/daniviga/django-ram.git
synced 2026-02-04 10:00:40 +01:00
Implement query optimization
This commit is contained in:
@@ -98,6 +98,13 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
|
||||
search_fields = ("title", "publisher__name", "authors__last_name")
|
||||
list_filter = ("publisher__name", "authors", "published")
|
||||
|
||||
def get_queryset(self, request):
|
||||
"""Optimize queryset with select_related and prefetch_related."""
|
||||
qs = super().get_queryset(request)
|
||||
return qs.select_related('publisher', 'shop').prefetch_related(
|
||||
'authors', 'tags', 'image', 'toc'
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
@@ -266,6 +273,13 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
|
||||
"scales__scale",
|
||||
)
|
||||
|
||||
def get_queryset(self, request):
|
||||
"""Optimize queryset with select_related and prefetch_related."""
|
||||
qs = super().get_queryset(request)
|
||||
return qs.select_related('manufacturer', 'shop').prefetch_related(
|
||||
'scales', 'tags', 'image'
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
@@ -490,6 +504,11 @@ class MagazineAdmin(SortableAdminBase, admin.ModelAdmin):
|
||||
"publisher__name",
|
||||
)
|
||||
|
||||
def get_queryset(self, request):
|
||||
"""Optimize queryset with select_related and prefetch_related."""
|
||||
qs = super().get_queryset(request)
|
||||
return qs.select_related('publisher').prefetch_related('tags')
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
|
||||
@@ -11,6 +11,7 @@ from django_countries.fields import CountryField
|
||||
|
||||
from ram.utils import DeduplicatedStorage
|
||||
from ram.models import BaseModel, Image, PropertyInstance
|
||||
from ram.managers import BookManager, CatalogManager, MagazineIssueManager
|
||||
from metadata.models import Scale, Manufacturer, Shop, Tag
|
||||
|
||||
|
||||
@@ -105,6 +106,8 @@ class Book(BaseBook):
|
||||
authors = models.ManyToManyField(Author, blank=True)
|
||||
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
||||
|
||||
objects = BookManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ["title"]
|
||||
|
||||
@@ -134,6 +137,8 @@ class Catalog(BaseBook):
|
||||
years = models.CharField(max_length=12)
|
||||
scales = models.ManyToManyField(Scale, related_name="catalogs")
|
||||
|
||||
objects = CatalogManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ["manufacturer", "publication_year"]
|
||||
|
||||
@@ -214,6 +219,8 @@ class MagazineIssue(BaseBook):
|
||||
null=True, blank=True, choices=MONTHS.items()
|
||||
)
|
||||
|
||||
objects = MagazineIssueManager()
|
||||
|
||||
class Meta:
|
||||
unique_together = ("magazine", "issue_number")
|
||||
ordering = [
|
||||
|
||||
@@ -59,6 +59,13 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin):
|
||||
search_fields = ("identifier",) + list_filter
|
||||
save_as = True
|
||||
|
||||
def get_queryset(self, request):
|
||||
"""Optimize queryset with select_related and prefetch_related."""
|
||||
qs = super().get_queryset(request)
|
||||
return qs.select_related(
|
||||
'company', 'scale'
|
||||
).prefetch_related('tags', 'consist_item')
|
||||
|
||||
@admin.display(description="Country")
|
||||
def country_flag(self, obj):
|
||||
return format_html(
|
||||
|
||||
@@ -8,6 +8,7 @@ from django.core.exceptions import ValidationError
|
||||
|
||||
from ram.models import BaseModel
|
||||
from ram.utils import DeduplicatedStorage
|
||||
from ram.managers import ConsistManager
|
||||
from metadata.models import Company, Scale, Tag
|
||||
from roster.models import RollingStock
|
||||
|
||||
@@ -35,6 +36,8 @@ class Consist(BaseModel):
|
||||
blank=True,
|
||||
)
|
||||
|
||||
objects = ConsistManager()
|
||||
|
||||
def __str__(self):
|
||||
return "{0} {1}".format(self.company, self.identifier)
|
||||
|
||||
|
||||
@@ -96,6 +96,16 @@ class GetData(View):
|
||||
def get_data(self, request):
|
||||
return (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
'decoder',
|
||||
'shop',
|
||||
)
|
||||
.prefetch_related('tags', 'image')
|
||||
.order_by(*get_items_ordering())
|
||||
.filter(self.filter)
|
||||
)
|
||||
@@ -132,6 +142,16 @@ class GetHome(GetData):
|
||||
max_items = min(settings.FEATURED_ITEMS_MAX, get_items_per_page())
|
||||
return (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
'decoder',
|
||||
'shop',
|
||||
)
|
||||
.prefetch_related('tags', 'image')
|
||||
.filter(featured=True)
|
||||
.order_by(*get_items_ordering(config="featured_items_ordering"))[
|
||||
:max_items
|
||||
@@ -200,6 +220,14 @@ class SearchObjects(View):
|
||||
# and manufacturer as well
|
||||
roster = (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
)
|
||||
.prefetch_related('tags', 'image')
|
||||
.filter(query)
|
||||
.distinct()
|
||||
.order_by(*get_items_ordering())
|
||||
@@ -209,6 +237,8 @@ class SearchObjects(View):
|
||||
if _filter is None:
|
||||
consists = (
|
||||
Consist.objects.get_published(request.user)
|
||||
.select_related('company', 'scale')
|
||||
.prefetch_related('tags', 'consist_item')
|
||||
.filter(
|
||||
Q(
|
||||
Q(identifier__icontains=search)
|
||||
@@ -220,6 +250,7 @@ class SearchObjects(View):
|
||||
data = list(chain(data, consists))
|
||||
books = (
|
||||
Book.objects.get_published(request.user)
|
||||
.prefetch_related('toc', 'image')
|
||||
.filter(
|
||||
Q(
|
||||
Q(title__icontains=search)
|
||||
@@ -231,6 +262,8 @@ class SearchObjects(View):
|
||||
)
|
||||
catalogs = (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('scales', 'image')
|
||||
.filter(
|
||||
Q(
|
||||
Q(manufacturer__name__icontains=search)
|
||||
@@ -242,6 +275,8 @@ class SearchObjects(View):
|
||||
data = list(chain(data, books, catalogs))
|
||||
magazine_issues = (
|
||||
MagazineIssue.objects.get_published(request.user)
|
||||
.select_related('magazine')
|
||||
.prefetch_related('toc', 'image')
|
||||
.filter(
|
||||
Q(
|
||||
Q(magazine__name__icontains=search)
|
||||
@@ -331,9 +366,16 @@ class GetManufacturerItem(View):
|
||||
)
|
||||
if search != "all":
|
||||
roster = get_list_or_404(
|
||||
RollingStock.objects.get_published(request.user).order_by(
|
||||
*get_items_ordering()
|
||||
),
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
)
|
||||
.prefetch_related('image')
|
||||
.order_by(*get_items_ordering()),
|
||||
Q(
|
||||
Q(manufacturer=manufacturer)
|
||||
& Q(item_number_slug__exact=search)
|
||||
@@ -349,6 +391,14 @@ class GetManufacturerItem(View):
|
||||
else:
|
||||
roster = (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
)
|
||||
.prefetch_related('image')
|
||||
.filter(
|
||||
Q(manufacturer=manufacturer)
|
||||
| Q(rolling_class__manufacturer=manufacturer)
|
||||
@@ -356,8 +406,11 @@ class GetManufacturerItem(View):
|
||||
.distinct()
|
||||
.order_by(*get_items_ordering())
|
||||
)
|
||||
catalogs = Catalog.objects.get_published(request.user).filter(
|
||||
manufacturer=manufacturer
|
||||
catalogs = (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('scales', 'image')
|
||||
.filter(manufacturer=manufacturer)
|
||||
)
|
||||
title = "Manufacturer: {0}".format(manufacturer)
|
||||
|
||||
@@ -405,6 +458,14 @@ class GetObjectsFiltered(View):
|
||||
|
||||
roster = (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
)
|
||||
.prefetch_related('tags', 'image')
|
||||
.filter(query)
|
||||
.distinct()
|
||||
.order_by(*get_items_ordering())
|
||||
@@ -415,6 +476,8 @@ class GetObjectsFiltered(View):
|
||||
if _filter == "scale":
|
||||
catalogs = (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('scales', 'image')
|
||||
.filter(scales__slug=search)
|
||||
.distinct()
|
||||
)
|
||||
@@ -423,6 +486,8 @@ class GetObjectsFiltered(View):
|
||||
try: # Execute only if query_2nd is defined
|
||||
consists = (
|
||||
Consist.objects.get_published(request.user)
|
||||
.select_related('company', 'scale')
|
||||
.prefetch_related('tags', 'consist_item')
|
||||
.filter(query_2nd)
|
||||
.distinct()
|
||||
)
|
||||
@@ -430,16 +495,21 @@ class GetObjectsFiltered(View):
|
||||
if _filter == "tag": # Books can be filtered only by tag
|
||||
books = (
|
||||
Book.objects.get_published(request.user)
|
||||
.prefetch_related('toc', 'tags', 'image')
|
||||
.filter(query_2nd)
|
||||
.distinct()
|
||||
)
|
||||
catalogs = (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('scales', 'tags', 'image')
|
||||
.filter(query_2nd)
|
||||
.distinct()
|
||||
)
|
||||
magazine_issues = (
|
||||
MagazineIssue.objects.get_published(request.user)
|
||||
.select_related('magazine')
|
||||
.prefetch_related('toc', 'tags', 'image')
|
||||
.filter(query_2nd)
|
||||
.distinct()
|
||||
)
|
||||
@@ -477,9 +547,29 @@ class GetObjectsFiltered(View):
|
||||
class GetRollingStock(View):
|
||||
def get(self, request, uuid):
|
||||
try:
|
||||
rolling_stock = RollingStock.objects.get_published(
|
||||
request.user
|
||||
).get(uuid=uuid)
|
||||
rolling_stock = (
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
'decoder',
|
||||
'shop',
|
||||
)
|
||||
.prefetch_related(
|
||||
'tags',
|
||||
'image',
|
||||
'property',
|
||||
'document',
|
||||
'journal',
|
||||
'rolling_class__property',
|
||||
'rolling_class__manufacturer',
|
||||
'decoder__document',
|
||||
)
|
||||
.get(uuid=uuid)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
|
||||
@@ -498,13 +588,22 @@ class GetRollingStock(View):
|
||||
)
|
||||
|
||||
consists = list(
|
||||
Consist.objects.get_published(request.user).filter(
|
||||
consist_item__rolling_stock=rolling_stock
|
||||
)
|
||||
Consist.objects.get_published(request.user)
|
||||
.select_related('company', 'scale')
|
||||
.prefetch_related('tags', 'consist_item')
|
||||
.filter(consist_item__rolling_stock=rolling_stock)
|
||||
)
|
||||
|
||||
trainset = list(
|
||||
RollingStock.objects.get_published(request.user)
|
||||
.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
)
|
||||
.prefetch_related('image')
|
||||
.filter(
|
||||
Q(
|
||||
Q(item_number__exact=rolling_stock.item_number)
|
||||
@@ -535,30 +634,62 @@ class Consists(GetData):
|
||||
title = "Consists"
|
||||
|
||||
def get_data(self, request):
|
||||
return Consist.objects.get_published(request.user).all()
|
||||
return (
|
||||
Consist.objects.get_published(request.user)
|
||||
.select_related('company', 'scale')
|
||||
.prefetch_related('tags', 'consist_item')
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
class GetConsist(View):
|
||||
def get(self, request, uuid, page=1):
|
||||
try:
|
||||
consist = Consist.objects.get_published(request.user).get(
|
||||
uuid=uuid
|
||||
consist = (
|
||||
Consist.objects.get_published(request.user)
|
||||
.select_related('company', 'scale')
|
||||
.prefetch_related(
|
||||
'tags',
|
||||
'consist_item',
|
||||
'consist_item__rolling_stock',
|
||||
'consist_item__rolling_stock__rolling_class',
|
||||
'consist_item__rolling_stock__rolling_class__company',
|
||||
'consist_item__rolling_stock__rolling_class__type',
|
||||
'consist_item__rolling_stock__manufacturer',
|
||||
'consist_item__rolling_stock__scale',
|
||||
'consist_item__rolling_stock__image',
|
||||
)
|
||||
.get(uuid=uuid)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
|
||||
# Fetch consist items with related rolling stock in one query
|
||||
consist_items = consist.consist_item.select_related(
|
||||
'rolling_stock',
|
||||
'rolling_stock__rolling_class',
|
||||
'rolling_stock__rolling_class__company',
|
||||
'rolling_stock__rolling_class__type',
|
||||
'rolling_stock__manufacturer',
|
||||
'rolling_stock__scale',
|
||||
).prefetch_related('rolling_stock__image')
|
||||
|
||||
# Filter items and loads
|
||||
data = list(
|
||||
RollingStock.objects.get_published(request.user).get(
|
||||
uuid=r.rolling_stock_id
|
||||
)
|
||||
for r in consist.consist_item.filter(load=False)
|
||||
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(
|
||||
RollingStock.objects.get_published(request.user).get(
|
||||
uuid=r.rolling_stock_id
|
||||
)
|
||||
for r in consist.consist_item.filter(load=True)
|
||||
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()
|
||||
)
|
||||
|
||||
paginator = Paginator(data, get_items_per_page())
|
||||
data = paginator.get_page(page)
|
||||
page_range = paginator.get_elided_page_range(
|
||||
@@ -739,14 +870,23 @@ class Books(GetData):
|
||||
title = "Books"
|
||||
|
||||
def get_data(self, request):
|
||||
return Book.objects.get_published(request.user).all()
|
||||
return (
|
||||
Book.objects.get_published(request.user)
|
||||
.prefetch_related('tags', 'image', 'toc')
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
class Catalogs(GetData):
|
||||
title = "Catalogs"
|
||||
|
||||
def get_data(self, request):
|
||||
return Catalog.objects.get_published(request.user).all()
|
||||
return (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('scales', 'tags', 'image')
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
class Magazines(GetData):
|
||||
@@ -755,6 +895,8 @@ class Magazines(GetData):
|
||||
def get_data(self, request):
|
||||
return (
|
||||
Magazine.objects.get_published(request.user)
|
||||
.select_related('publisher')
|
||||
.prefetch_related('tags')
|
||||
.order_by(Lower("name"))
|
||||
.annotate(
|
||||
issues=Count(
|
||||
@@ -772,12 +914,19 @@ class Magazines(GetData):
|
||||
class GetMagazine(View):
|
||||
def get(self, request, uuid, page=1):
|
||||
try:
|
||||
magazine = Magazine.objects.get_published(request.user).get(
|
||||
uuid=uuid
|
||||
magazine = (
|
||||
Magazine.objects.get_published(request.user)
|
||||
.select_related('publisher')
|
||||
.prefetch_related('tags')
|
||||
.get(uuid=uuid)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
data = list(magazine.issue.get_published(request.user).all())
|
||||
data = list(
|
||||
magazine.issue.get_published(request.user)
|
||||
.prefetch_related('image', 'toc')
|
||||
.all()
|
||||
)
|
||||
paginator = Paginator(data, get_items_per_page())
|
||||
data = paginator.get_page(page)
|
||||
page_range = paginator.get_elided_page_range(
|
||||
@@ -800,9 +949,11 @@ class GetMagazine(View):
|
||||
class GetMagazineIssue(View):
|
||||
def get(self, request, uuid, magazine, page=1):
|
||||
try:
|
||||
issue = MagazineIssue.objects.get_published(request.user).get(
|
||||
uuid=uuid,
|
||||
magazine__uuid=magazine,
|
||||
issue = (
|
||||
MagazineIssue.objects.get_published(request.user)
|
||||
.select_related('magazine')
|
||||
.prefetch_related('property', 'document', 'image', 'toc')
|
||||
.get(uuid=uuid, magazine__uuid=magazine)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise Http404
|
||||
@@ -823,9 +974,18 @@ class GetMagazineIssue(View):
|
||||
class GetBookCatalog(View):
|
||||
def get_object(self, request, uuid, selector):
|
||||
if selector == "book":
|
||||
return Book.objects.get_published(request.user).get(uuid=uuid)
|
||||
return (
|
||||
Book.objects.get_published(request.user)
|
||||
.prefetch_related('property', 'document', 'image', 'toc', 'tags')
|
||||
.get(uuid=uuid)
|
||||
)
|
||||
elif selector == "catalog":
|
||||
return Catalog.objects.get_published(request.user).get(uuid=uuid)
|
||||
return (
|
||||
Catalog.objects.get_published(request.user)
|
||||
.select_related('manufacturer')
|
||||
.prefetch_related('property', 'document', 'image', 'scales', 'tags')
|
||||
.get(uuid=uuid)
|
||||
)
|
||||
else:
|
||||
raise Http404
|
||||
|
||||
|
||||
@@ -4,12 +4,20 @@ from django.core.exceptions import FieldError
|
||||
|
||||
class PublicManager(models.Manager):
|
||||
def get_published(self, user):
|
||||
"""
|
||||
Get published items based on user authentication status.
|
||||
Returns all items for authenticated users, only published for anonymous.
|
||||
"""
|
||||
if user.is_authenticated:
|
||||
return self.get_queryset()
|
||||
else:
|
||||
return self.get_queryset().filter(published=True)
|
||||
|
||||
def get_public(self, user):
|
||||
"""
|
||||
Get public items based on user authentication status.
|
||||
Returns all items for authenticated users, only non-private for anonymous.
|
||||
"""
|
||||
if user.is_authenticated:
|
||||
return self.get_queryset()
|
||||
else:
|
||||
@@ -17,3 +25,124 @@ class PublicManager(models.Manager):
|
||||
return self.get_queryset().filter(private=False)
|
||||
except FieldError:
|
||||
return self.get_queryset().filter(property__private=False)
|
||||
|
||||
|
||||
class RollingStockManager(PublicManager):
|
||||
"""Optimized manager for RollingStock with prefetch methods."""
|
||||
|
||||
def with_related(self):
|
||||
"""
|
||||
Optimize queryset by prefetching commonly accessed related objects.
|
||||
Use this for list views to avoid N+1 queries.
|
||||
"""
|
||||
return self.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
'decoder',
|
||||
'shop',
|
||||
).prefetch_related('tags', 'image')
|
||||
|
||||
def with_details(self):
|
||||
"""
|
||||
Optimize queryset for detail views with all related objects.
|
||||
Includes properties, documents, and journal entries.
|
||||
"""
|
||||
return self.with_related().prefetch_related(
|
||||
'property',
|
||||
'document',
|
||||
'journal',
|
||||
'rolling_class__property',
|
||||
'rolling_class__manufacturer',
|
||||
'decoder__document',
|
||||
)
|
||||
|
||||
def get_published_with_related(self, user):
|
||||
"""
|
||||
Convenience method combining get_published with related objects.
|
||||
"""
|
||||
return self.get_published(user).with_related()
|
||||
|
||||
|
||||
class ConsistManager(PublicManager):
|
||||
"""Optimized manager for Consist with prefetch methods."""
|
||||
|
||||
def with_related(self):
|
||||
"""
|
||||
Optimize queryset by prefetching commonly accessed related objects.
|
||||
Note: Consist.image is a direct ImageField, not a relation.
|
||||
"""
|
||||
return self.select_related('company', 'scale').prefetch_related(
|
||||
'tags', 'consist_item'
|
||||
)
|
||||
|
||||
def with_rolling_stock(self):
|
||||
"""
|
||||
Optimize queryset including consist items and their rolling stock.
|
||||
Use for detail views showing consist composition.
|
||||
"""
|
||||
return self.with_related().prefetch_related(
|
||||
'consist_item__rolling_stock',
|
||||
'consist_item__rolling_stock__rolling_class',
|
||||
'consist_item__rolling_stock__rolling_class__company',
|
||||
'consist_item__rolling_stock__rolling_class__type',
|
||||
'consist_item__rolling_stock__manufacturer',
|
||||
'consist_item__rolling_stock__scale',
|
||||
'consist_item__rolling_stock__image',
|
||||
)
|
||||
|
||||
|
||||
class BookManager(PublicManager):
|
||||
"""Optimized manager for Book/Catalog with prefetch methods."""
|
||||
|
||||
def with_related(self):
|
||||
"""
|
||||
Optimize queryset by prefetching commonly accessed related objects.
|
||||
"""
|
||||
return self.select_related('publisher', 'shop').prefetch_related(
|
||||
'authors', 'tags', 'image', 'toc'
|
||||
)
|
||||
|
||||
def with_details(self):
|
||||
"""
|
||||
Optimize queryset for detail views with properties and documents.
|
||||
"""
|
||||
return self.with_related().prefetch_related('property', 'document')
|
||||
|
||||
|
||||
class CatalogManager(PublicManager):
|
||||
"""Optimized manager for Catalog with prefetch methods."""
|
||||
|
||||
def with_related(self):
|
||||
"""
|
||||
Optimize queryset by prefetching commonly accessed related objects.
|
||||
"""
|
||||
return self.select_related('manufacturer', 'shop').prefetch_related(
|
||||
'scales', 'tags', 'image'
|
||||
)
|
||||
|
||||
def with_details(self):
|
||||
"""
|
||||
Optimize queryset for detail views with properties and documents.
|
||||
"""
|
||||
return self.with_related().prefetch_related('property', 'document')
|
||||
|
||||
|
||||
class MagazineIssueManager(PublicManager):
|
||||
"""Optimized manager for MagazineIssue with prefetch methods."""
|
||||
|
||||
def with_related(self):
|
||||
"""
|
||||
Optimize queryset by prefetching commonly accessed related objects.
|
||||
"""
|
||||
return self.select_related('magazine').prefetch_related(
|
||||
'tags', 'image', 'toc'
|
||||
)
|
||||
|
||||
def with_details(self):
|
||||
"""
|
||||
Optimize queryset for detail views with properties and documents.
|
||||
"""
|
||||
return self.with_related().prefetch_related('property', 'document')
|
||||
|
||||
@@ -158,6 +158,19 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
||||
)
|
||||
save_as = True
|
||||
|
||||
def get_queryset(self, request):
|
||||
"""Optimize queryset with select_related and prefetch_related."""
|
||||
qs = super().get_queryset(request)
|
||||
return qs.select_related(
|
||||
'rolling_class',
|
||||
'rolling_class__company',
|
||||
'rolling_class__type',
|
||||
'manufacturer',
|
||||
'scale',
|
||||
'decoder',
|
||||
'shop',
|
||||
).prefetch_related('tags', 'image')
|
||||
|
||||
@admin.display(description="Country")
|
||||
def country_flag(self, obj):
|
||||
return format_html(
|
||||
|
||||
@@ -11,7 +11,7 @@ from tinymce import models as tinymce
|
||||
|
||||
from ram.models import BaseModel, Image, PropertyInstance
|
||||
from ram.utils import DeduplicatedStorage, slugify
|
||||
from ram.managers import PublicManager
|
||||
from ram.managers import PublicManager, RollingStockManager
|
||||
from metadata.models import (
|
||||
Scale,
|
||||
Manufacturer,
|
||||
@@ -248,7 +248,7 @@ class RollingStockJournal(models.Model):
|
||||
class Meta:
|
||||
ordering = ["date", "rolling_stock"]
|
||||
|
||||
objects = PublicManager()
|
||||
objects = RollingStockManager()
|
||||
|
||||
|
||||
# @receiver(models.signals.post_delete, sender=Cab)
|
||||
|
||||
Reference in New Issue
Block a user