In my Django model, I defined a @property which worked nicely and the property can be shown in the admin list_display without any problems.
I need this property not only in admin but in my code logic in other places as well, so it makes sense to have it as property for my model.
Now I wanted to make the column of this property sortable, and with help of the Django documentation of the When object, this StackOverflow question for the F()-calculation and this link for the sorting I managed to build the working solution shown below.
The reason for posing a question here is: In fact, I implemented my logic twice, once in python and once in form of an expression, which is against the design rule of implementing the same logic only once. So I wanted to ask whether I missed a better solution to my problem. Any ideas are appreciated.
This is the model (identifyers modified):
class De(models.Model):
fr = models.BooleanField("[...]")
de = models.SmallIntegerField("[...]")
gd = models.SmallIntegerField("[...]")
na = models.SmallIntegerField("[...]")
# [several_attributes, Meta, __str__() removed for readability]
@property
def s_d(self):
if self.fr:
return self.de
else:
return self.gd + self.na
This is the Model Admin:
class DeAdmin(admin.ModelAdmin):
list_display = ("[...]", "s_d", "gd", "na", "de", "fr" )
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_s_d=Case(
When(fr=True, then='s_d'),
When(fr=False, then=F('gd') + F('na')),
default=Value(0),
output_field=IntegerField(),
)
)
return queryset
def s_d(self, obj):
return obj._s_d
s_d.admin_order_field = '_s_d'
If there is no other way, I would also appreciate confirmation of the fact as an answer.