【问题标题】:Django annotate value based on another model fieldDjango基于另一个模型字段注释值
【发布时间】:2021-10-09 21:19:39
【问题描述】:

我有这两个模型,案例和专业,就像这样:

class Case(models.Model):
   ...
   judge = models.CharField()
   ....

class Specialty(models.Model):
   name = models.CharField()
   sys_num = models.IntegerField()

我知道这听起来像一个非常奇怪的结构,但请尝试与我裸露: Case 模型中的字段judge 引用Specialty 实例sys_num 值(judge 是一个字符字段,但它始终带有一个整数)(每个Specialty 实例都有一个唯一的sys_num) .所以我可以使用类似这样的方法获取与特定Case 实例相关的Specialty 名称:

my_pk = #some number here...
my_case_judge = Case.objects.get(pk=my_pk).judge
my_specialty_name = Specialty.objects.get(sys_num=my_case_judge)

我知道这听起来很奇怪,但我无法更改表的基础架构,只需使用 sql 和 Django 的 orm 解决它。

我的问题是:我想在 Cases 的查询集中注释 Specialty 名称已经调用了 values()

我只能使用CaseWhen 让它工作,但它不是动态的。如果我添加更多 Specialty 实例,我将不得不手动更改代码。

 cases.annotate(
         specialty=Case(
             When(judge=0, then=Value('name 0 goes here')),
             When(judge=1, then=Value('name 1 goes here')),
             When(judge=2, then=Value('name 2 goes here')),
             When(judge=3, then=Value('name 3 goes here')),
             ...

这可以动态完成吗?我查看了django's query reference 文档,但无法使用那里指定的工具生成有效的解决方案。

【问题讨论】:

  • 那么你应该使用ForeignKeyspeciality,这真的是“丑陋”的造型。

标签: python mysql django django-orm


【解决方案1】:

您可以使用subquery expression

from django.db.models import OuterRef, Subquery

Case.objects.annotate(
    specialty=Subquery(
        Specialty.objects.filter(sys_num=OuterRef('judge')).values('name')[:1]
    )
)

对于某些数据库,甚至可能需要强制转换:

from django.db.models import IntegerField, OuterRef, Subquery
from django.db.models.functions import Cast

Case.objects.annotate(
    specialty=Subquery(
        Specialty.objects.filter(sys_num=Cast(
            OuterRef('judge'),
            output_field=IntegerField()
        )).values('name')[:1]
    )
)

但是建模非常很糟糕。通常最好使用ForeignKey,这将保证judge 只能指向一个有效的案例(所以引用完整性),会在字段上创建索引,它也会使Django ORM 更有效因为它允许使用(相对)小查询进行更高级的查询。

【讨论】:

  • 哇,这行得通!我很惊讶。非常感谢你:))
猜你喜欢
  • 2021-01-31
  • 2015-09-26
  • 2014-12-25
  • 2020-06-23
  • 2011-05-21
  • 2019-02-16
  • 1970-01-01
  • 2019-03-11
  • 2010-11-13
相关资源
最近更新 更多