Как я могу аннотировать() либо по связанному @свойству модели, либо по обратному отношению?
У меня есть следующие модели:
class DropTemplate(TimeStampedModel):
author = models.ForeignKey(Author, on_delete=models.PROTECT)
@property
def start_time(self) -> Union[None, str]:
earliest_collection = (
self.collectiontemplates.filter(drop_template_id=self.id, visible_start_time__isnull=False)
.only("visible_start_time")
.order_by("visible_start_time")
.first()
)
if earliest_collection is None:
return None
else:
return earliest_collection.visible_start_time
class CollectionTemplate(TimeStampedModel):
drop_template = models.ForeignKey(
DropTemplate, related_name="collectiontemplates", on_delete=models.PROTECT
)
visible_start_time = models.DateTimeField(null=True, blank=True)
И следующий Django Rest Framework ModelViewSet
:
class DropTemplateViewSet(viewsets.ModelViewSet):
serializer_class = DropTemplateSerializer
filter_backends = [DjangoFilterBackend, OrderingFilter]
ordering_fields = ["start_time"]
ordering = ["start_time"]
def get_queryset(self):
return DropTemplate.objects.annotate(start_time= # <-- WHAT DO I INPUT HERE?
).filter(author__id=self.kwargs["author_pk"])
Я уже пытался поместить Subquery()
в метод get_queryset
, поскольку, похоже, я не могу напрямую использовать @свойство, поскольку оно не находится на уровне БД.
def get_queryset(self):
collection_templates = CollectionTemplate.objects.filter(visible_start_time__isnull=False).only("visible_start_time")
return DropTemplate.objects.annotate(start_time=Subquery(collection_templates, output_field=DateTimeField())).filter(author__id=self.kwargs["author_pk"])
Однако, я получаю следующую ошибку:
subquery must return only one column
Я новичок в Django Query Aggregation и потратил слишком много времени, пытаясь разобраться в этом самостоятельно. Я надеюсь, что кто-нибудь здесь сможет дать мне некоторые рекомендации.
Спасибо!
Решением было обновление моего метода get_queryset()
до следующего:
def get_queryset(self):
return DropTemplate.objects.annotate(start_time=F("collectiontemplates__visible_start_time")).filter(publisher__id=self.kwargs["publisher_pk"])
Когда я первоначально сделал это, я получил cannot set attribute
ошибку, поскольку было столкновение имен с моим @property.
Я переименовал свое @свойство DropTemplate
в earliest_start_time
, чтобы избежать столкновения.
DropTemplate.objects.annotate(start_time=Subquery(collection_templates.values("visible_start_time")[:1])).filter(publisher__id=self.kwargs[author_pk"])
был решением