Reputation: 270
I have a choice filed and i need to sort it based on the order in CHOICES tuple and this model.py:
class MeetingMember(models.Model):
CHOICES = (
("H", "Host"),
("A", "Accepted"),
("R", "Rejected"),
("I", "Invited" )
)
status = models.CharField(max_length=9, choices=CHOICES, default="I")
i have already tried meta ordering :
class Meta:
ordering = ('status',)
but it is not working i need to sort it in Host,Accepted,Rejected,Invited
Upvotes: 0
Views: 69
Reputation: 266
You can try to exploit the Replace
function (https://docs.djangoproject.com/en/3.2/ref/models/database-functions/#replace). The strategy is to annotate a new field with a value built in a way that its alphabetical order matches the custom order you want in the original field:
from django.db.models import F, Value
from django.db.models.functions import Replace
# This generates a dictionary like {'0': 'H', '1': 'A', ...}
mapped_choices = {str(n): CHOICES[n][0] for n in range(len(CHOICES))}
# For each mapped choice we create a replacer
replacers = [
Replace('status_for_ordering', Value(original), Value(replacement))
for replacement, original in mapped_choices.items()
]
qs = MeetingMember.objects.all().annotate(status_for_ordering=F('status'))
for replacer in replacers:
qs = qs.annotate(status_for_ordering=replacer)
# Of course here you can still filter or do other operations before ordering
qs = qs.order_by('status_for_ordering')
This solution should work for your example but of course would need some adjustments in case the replacements starts to conflict each others (f.i. if one of your original status values contains a digit).
Upvotes: 1