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",
|
"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)
|
@admin.register(CertificationDefinition)
|
||||||
class CertificationDefinitionAdmin(admin.ModelAdmin):
|
class CertificationDefinitionAdmin(admin.ModelAdmin):
|
||||||
@ -64,6 +72,10 @@ class CertificationAdmin(admin.ModelAdmin):
|
|||||||
autocomplete_fields = ["member"]
|
autocomplete_fields = ["member"]
|
||||||
exclude = ["shop_lead_notified"]
|
exclude = ["shop_lead_notified"]
|
||||||
|
|
||||||
|
def get_queryset(self, request):
|
||||||
|
qs = super().get_queryset(request)
|
||||||
|
return qs.prefetch_related("certification_version__definition__department")
|
||||||
|
|
||||||
@admin.display(
|
@admin.display(
|
||||||
description="Certification Name",
|
description="Certification Name",
|
||||||
ordering="certification_version__definition__certification_name",
|
ordering="certification_version__definition__certification_name",
|
||||||
@ -87,8 +99,8 @@ class CertificationAdmin(admin.ModelAdmin):
|
|||||||
return obj.certification_version.semantic_version()
|
return obj.certification_version.semantic_version()
|
||||||
|
|
||||||
@admin.display(description="Current", boolean=True)
|
@admin.display(description="Current", boolean=True)
|
||||||
def certification_version__is_current(self, obj):
|
def is_current(self, obj):
|
||||||
return obj.certification_version.is_current()
|
return obj.certification_version.is_current
|
||||||
|
|
||||||
@admin.display(
|
@admin.display(
|
||||||
description="Department",
|
description="Department",
|
||||||
@ -101,7 +113,7 @@ class CertificationAdmin(admin.ModelAdmin):
|
|||||||
"certification_name",
|
"certification_name",
|
||||||
"name",
|
"name",
|
||||||
"certification_semantic_version",
|
"certification_semantic_version",
|
||||||
"certification_version__is_current",
|
"is_current",
|
||||||
"certification_department",
|
"certification_department",
|
||||||
"date",
|
"date",
|
||||||
"shop_lead_notified",
|
"shop_lead_notified",
|
||||||
|
@ -2,6 +2,7 @@ import re
|
|||||||
|
|
||||||
from semver import VersionInfo
|
from semver import VersionInfo
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import ExpressionWrapper, OuterRef, Q, Subquery
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
|
|
||||||
from membershipworks.models import Member, Flag as MembershipWorksFlag
|
from membershipworks.models import Member, Flag as MembershipWorksFlag
|
||||||
@ -91,12 +92,29 @@ class CertificationDefinition(models.Model):
|
|||||||
ordering = ("certification_name", "department")
|
ordering = ("certification_name", "department")
|
||||||
|
|
||||||
def latest_version(self) -> "CertificationVersion":
|
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):
|
class CertificationVersion(models.Model):
|
||||||
|
objects = CertificationVersionManager()
|
||||||
|
|
||||||
definition = models.ForeignKey(
|
definition = models.ForeignKey(
|
||||||
CertificationDefinition, on_delete=models.PROTECT, db_column="Certification"
|
CertificationDefinition, on_delete=models.PROTECT, db_column="Certification"
|
||||||
)
|
)
|
||||||
@ -117,6 +135,8 @@ class CertificationVersion(models.Model):
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
ordering = ("major", "minor", "patch", "prerelease", "approval_date")
|
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:
|
def semantic_version(self) -> VersionInfo:
|
||||||
return VersionInfo(
|
return VersionInfo(
|
||||||
@ -127,18 +147,6 @@ class CertificationVersion(models.Model):
|
|||||||
self.approval_date.isoformat() if self.approval_date is not None else None,
|
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):
|
class Certification(models.Model):
|
||||||
number = models.AutoField(db_column="Number", primary_key=True)
|
number = models.AutoField(db_column="Number", primary_key=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user