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

Вернуться на верх