Django 根据另一个模型字段注释值
Django annotate value based on another model field
我有这两个模型,Cases 和 Specialties,就像这样:
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
的查询集中注释 values()
.
的名称
我只设法使用 Case
和 When
让它工作,但它不是动态的。如果我添加更多 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 文档,但无法使用此处指定的工具生成有效的解决方案。
您可以使用 subquery expression:
from django.db.models import OuterRef, Subquery
Case.objects.annotate(
specialty=<strong>Subquery(</strong>
Specialty.objects.filter(<strong>sys_num=OuterRef('judge')</strong>).values('name')[:1]
<strong>)</strong>
)
对于某些数据库,甚至可能需要转换:
from django.db.models import IntegerField, OuterRef, Subquery
from django.db.models.functions import Cast
Case.objects.annotate(
specialty=<strong>Subquery(</strong>
Specialty.objects.filter(sys_num=<b>Cast(</b>
OuterRef('judge'),
output_field=IntegerField()
<b>)</b>).values('name')[:1]
<strong>)</strong>
)
但是建模非常不好。通常最好使用 ForeignKey
,这将保证 judge
只能指向有效的情况(因此引用完整性),将在字段上创建索引,并且还会使Django ORM 更有效,因为它允许使用(相对)小查询进行更高级的查询。
我有这两个模型,Cases 和 Specialties,就像这样:
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
的查询集中注释 values()
.
我只设法使用 Case
和 When
让它工作,但它不是动态的。如果我添加更多 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 文档,但无法使用此处指定的工具生成有效的解决方案。
您可以使用 subquery expression:
from django.db.models import OuterRef, Subquery
Case.objects.annotate(
specialty=<strong>Subquery(</strong>
Specialty.objects.filter(<strong>sys_num=OuterRef('judge')</strong>).values('name')[:1]
<strong>)</strong>
)
对于某些数据库,甚至可能需要转换:
from django.db.models import IntegerField, OuterRef, Subquery
from django.db.models.functions import Cast
Case.objects.annotate(
specialty=<strong>Subquery(</strong>
Specialty.objects.filter(sys_num=<b>Cast(</b>
OuterRef('judge'),
output_field=IntegerField()
<b>)</b>).values('name')[:1]
<strong>)</strong>
)
但是建模非常不好。通常最好使用 ForeignKey
,这将保证 judge
只能指向有效的情况(因此引用完整性),将在字段上创建索引,并且还会使Django ORM 更有效,因为它允许使用(相对)小查询进行更高级的查询。