Django для начинающих: Как упорядочить набор запросов по свойству
У меня есть модель:
class Project(models.Model):
title = models.CharField("Project title", max_length=128)
start_date = models.DateField("Project start date", blank=True, null=True)
end_date = models.DateField("Project end date", blank=True, null=True)
@property
def has_ended(self):
return self.end_date is not None and self.end_date < timezone.now().date()
Я хочу упорядочить проекты по двум полям: start_date (desc), а также показать проекты, которые не закончились первыми. Я знаю, что не могу упорядочить по свойству, поэтому я попробовал следующее решение:
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.all().order_by("-start_date")
queryset = sorted(queryset, key=lambda a: a.has_ended)
serializer_class = ProjectSerializer
permission_classes = [permissions.IsAuthenticated]
, на который уже был дан ответ в других сообщениях с этим вопросом. Однако я все еще получаю следующую ошибку:
AttributeError: 'list' object has no attribute 'model'
Я также попробовал использовать аннотации Django следующим образом:
queryset = Project.objects.annotate(has_ended=F('start_date')-F('end_date')).order_by('has_ended', '-start_date')
Но сервер возвращает эту ошибку:
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 78, in __iter__
django_1 | setattr(obj, attr_name, row[col_pos])
django_1 | AttributeError: can't set attribute
У меня закончились идеи о том, как добиться желаемого поведения. Может ли кто-нибудь помочь мне в этом?
Здесь вы изменяете queryset
атрибут на list
экземпляр:
queryset = sorted(queryset, key=lambda a: a.has_ended)
Вы не можете этого сделать, потому что представлению нужен соответствующий QuerySet
объект.
Вы можете использовать простой фильтр, который чистый Django QuerySet
может оценить:
queryset = Project.objects.filter(end_date__lt=timezone.now().date()).order_by("-start_date")
Выражение lt
означает less than
. Двойное подчеркивание разделяет части логической цепочки, по которым вы фильтруете.
Как сказал @NixonSparrow, такого поведения можно добиться, просто упорядочив по конечной дате desc