Reputation: 489
I have a model with a date
field and a following method:
class Pm(models.Model):
mydate = models.DateField()
@property
def due_date(self):
today = timezone.localtime(timezone.now()).date()
if self.mydate < today:
return today
else:
return self.mydate
How can I order myModel.objects.all()
based on the return of due_date
function?
I tried:
qs = sorted(Pm.objects.all(), key=lambda a: a.due_date(), reverse=True)
but it returns error:
'datetime.date' object is not callable
UPDATE Based on Sami's suggestion:
@staticmethod
def due_date(obj):
today = timezone.localtime(timezone.now()).date()
if obj.pm_date < today:
return today
else:
return obj.pm_date
qs = sorted(Pm.objects.all(), key=Pm.due_date, reverse=True)
Seems to work, except it returns a list instead of a queryset.
What method should I use to get a queryset?
Upvotes: 1
Views: 690
Reputation:
Honestly, I wouldn't sort it in python. For two reasons:
And since you ultimately want a queryset, just keep it simple:
qs = Pm.objects.order_by('-mydate')
# Now we can display the due date property when we render things:
for pm in qs:
print(pm.due_date)
Upvotes: 2
Reputation: 381
I think you need to make your method due_date a static method or separate it from model, method gets the obj and return a date, and then use this method in sorted method. Something like this
def due_date(obj):
today = timezone.localtime(timezone.now()).date()
if obj.date < today:
return today
else:
return obj.date
qs = sorted(Pm.objects.all(), key=due_date, reverse=True)
If you make this method static in the Model class, then use it as:
qs = sorted(Pm.objects.all(), key=PM.due_date, reverse=True)
Otherwise you need to annotate and then use order_by of the queryset. annotation with conditional expressions F-expressions
something like this (it may not be the exact solution but you need to do something like this):
from django.db.models import Case, DateField, Value, When
qs = Pm.objects.annotate(
due_date=Case(
When(date__lt=today, then=Value(today)),
default=F("date"),
output_field=DateField(),
)
)
qs.order_by("due_date")
Upvotes: 2