Django annotate field value from another model

会有一股神秘感。 提交于 2021-01-27 19:23:23

问题


I want to annotate MyModel queryset with a value from another History model. My models relations are the following:

class Stage(models.Model):
    name = models.CharField()


class History(models.Model):
    mymodel = models.ForeignKey(
        MyModel,
        on_delete=models.CASCADE,
    )
    stage = models.ForeignKey(
        Stage,
        on_delete=models.DO_NOTHING
     )
    created_at = models.DateTimeField(
        auto_now_add=True
    )

class MyModel(models.Model):
    id = models.AutoField(
        primary_key=True,
    )
    ...

Approximate operation I'd like to perform in the ViewSet (order_by I need to get the latest stage):

class MyModelViewSet(viewsets.ModelViewSet):
    ...
    def get_queryset(self):
        qs = super(MyModelViewSet, self).get_queryset()
        qs = qs.annotate(last_stage_name=Value(
            History.objects.filter(mymodel__id=F('id')).order_by('-created_at')[0].stage.name,
            output_field=CharField()))

But I get the same stage for all objects from the first object instead of the latest stage of every object, so the logics of operation is wrong. I suppose I should get rid of History.objects.filter but can't find appropriate solution.


回答1:


You can work with a Subquery expression [Django-doc]:

from django.db.models import OuterRef, Subquery

class MyModelViewSet(viewsets.ModelViewSet):
    
    # …
    
    def get_queryset(self):
        return super().get_queryset().annotate(
            last_stage_name=Subquery(
                History.objects.filter(
                    mymodel_id=OuterRef('pk')
                ).order_by('-created_at').values('stage__name')[:1]
            )
        )


来源:https://stackoverflow.com/questions/64391494/django-annotate-field-value-from-another-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!