paperwork: Convert CertificationVersion is_current/latest to annotations
Pretty sigificantly improves performance of views that use it
This commit is contained in:
parent
1dd4825a99
commit
bb0e5abad5
@ -37,6 +37,14 @@ class CertificationVersionInline(admin.TabularInline):
|
||||
"is_current",
|
||||
)
|
||||
|
||||
@admin.display(description="Latest", boolean=True)
|
||||
def is_latest(self, obj):
|
||||
return obj.is_latest
|
||||
|
||||
@admin.display(description="Current", boolean=True)
|
||||
def is_current(self, obj):
|
||||
return obj.is_current
|
||||
|
||||
|
||||
@admin.register(CertificationDefinition)
|
||||
class CertificationDefinitionAdmin(admin.ModelAdmin):
|
||||
@ -64,6 +72,10 @@ class CertificationAdmin(admin.ModelAdmin):
|
||||
autocomplete_fields = ["member"]
|
||||
exclude = ["shop_lead_notified"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
qs = super().get_queryset(request)
|
||||
return qs.prefetch_related("certification_version__definition__department")
|
||||
|
||||
@admin.display(
|
||||
description="Certification Name",
|
||||
ordering="certification_version__definition__certification_name",
|
||||
@ -87,8 +99,8 @@ class CertificationAdmin(admin.ModelAdmin):
|
||||
return obj.certification_version.semantic_version()
|
||||
|
||||
@admin.display(description="Current", boolean=True)
|
||||
def certification_version__is_current(self, obj):
|
||||
return obj.certification_version.is_current()
|
||||
def is_current(self, obj):
|
||||
return obj.certification_version.is_current
|
||||
|
||||
@admin.display(
|
||||
description="Department",
|
||||
@ -101,7 +113,7 @@ class CertificationAdmin(admin.ModelAdmin):
|
||||
"certification_name",
|
||||
"name",
|
||||
"certification_semantic_version",
|
||||
"certification_version__is_current",
|
||||
"is_current",
|
||||
"certification_department",
|
||||
"date",
|
||||
"shop_lead_notified",
|
||||
|
@ -2,6 +2,7 @@ import re
|
||||
|
||||
from semver import VersionInfo
|
||||
from django.db import models
|
||||
from django.db.models import ExpressionWrapper, OuterRef, Q, Subquery
|
||||
from django.core.validators import RegexValidator
|
||||
|
||||
from membershipworks.models import Member, Flag as MembershipWorksFlag
|
||||
@ -91,12 +92,29 @@ class CertificationDefinition(models.Model):
|
||||
ordering = ("certification_name", "department")
|
||||
|
||||
def latest_version(self) -> "CertificationVersion":
|
||||
all_versions = CertificationVersion.objects.filter(definition=self)
|
||||
return self.certificationversion_set.latest()
|
||||
|
||||
return max(all_versions, key=lambda version: version.semantic_version())
|
||||
|
||||
class CertificationVersionManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
latest = qs.filter(definition__pk=OuterRef("definition__pk"))
|
||||
return qs.annotate(
|
||||
is_latest=ExpressionWrapper(
|
||||
Q(pk=Subquery(latest.values("pk")[:1])),
|
||||
output_field=models.BooleanField(),
|
||||
),
|
||||
# TODO: should do a more correct comparison than just major version
|
||||
is_current=ExpressionWrapper(
|
||||
Q(major=Subquery(latest.values("major")[:1])),
|
||||
output_field=models.BooleanField(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class CertificationVersion(models.Model):
|
||||
objects = CertificationVersionManager()
|
||||
|
||||
definition = models.ForeignKey(
|
||||
CertificationDefinition, on_delete=models.PROTECT, db_column="Certification"
|
||||
)
|
||||
@ -117,6 +135,8 @@ class CertificationVersion(models.Model):
|
||||
)
|
||||
]
|
||||
ordering = ("major", "minor", "patch", "prerelease", "approval_date")
|
||||
get_latest_by = ("major", "minor", "patch", "prerelease", "approval_date")
|
||||
base_manager_name = "objects"
|
||||
|
||||
def semantic_version(self) -> VersionInfo:
|
||||
return VersionInfo(
|
||||
@ -127,18 +147,6 @@ class CertificationVersion(models.Model):
|
||||
self.approval_date.isoformat() if self.approval_date is not None else None,
|
||||
)
|
||||
|
||||
def is_latest(self) -> bool:
|
||||
return self.definition.latest_version() == self
|
||||
|
||||
is_latest.boolean = True
|
||||
|
||||
def is_current(self) -> bool:
|
||||
"""Returns true if this version compatible with the latest version"""
|
||||
# TODO: should do a more correct comparison than just major version
|
||||
return self.definition.latest_version().major == self.major
|
||||
|
||||
is_current.boolean = True
|
||||
|
||||
|
||||
class Certification(models.Model):
|
||||
number = models.AutoField(db_column="Number", primary_key=True)
|
||||
|
Loading…
Reference in New Issue
Block a user