Django注释另一个模型的字段值 [英] Django annotate field value from another model

查看:39
本文介绍了Django注释另一个模型的字段值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用另一个历史记录模型中的值注释MyModel查询集.我的模型关系如下:

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,
    )
    ...

我想在ViewSet中执行的近似操作(order_by,我需要获取最新的阶段):

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()))

但是我从第一个对象得到的所有对象处于同一阶段,而不是从每个对象的最新阶段得到,因此操作逻辑是错误的.我想我应该摆脱History.objects.filter但找不到合适的解决方案.

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.

推荐答案

您可以使用 子查询 表达式[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]
            )
        )

这篇关于Django注释另一个模型的字段值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆