Django中QuerySet使用values()处理外键及Union查询问题
解决思路与方法
1. 先排查数据和外键配置
先查CompanyTemplateMessage的creator外键是不是设了null=True,要是的话,部分记录返回null是正常的;如果外键是必填的(null=False),那大概率是数据有问题——比如关联的User被删了但外键没级联删除,得先把数据修了。
2. 用F表达式正确关联外键字段
直接在values()里写creator__id或creator__email返回null,大概率是Django没正确生成JOIN查询。改用F()表达式来引用关联字段,确保查询时能关联到User表:
from django.db.models import F # 处理公司模板消息的查询集,明确关联用户字段 company_qs = CompanyTemplateMessage.objects.values( 'id', 'template_name', # 替换成你实际需要的业务字段 creator_id=F('creator__id'), creator_email=F('creator__email') )
3. 对齐两个查询集的字段
Union要求两个QuerySet的字段数量、类型、名称完全一致。如果DefaultTemplateMessage没有creator相关字段,用Value()填充默认值,还要指定字段类型保证匹配:
from django.db.models import Value, IntegerField, CharField # 处理默认模板消息的查询集,对齐字段 default_qs = DefaultTemplateMessage.objects.values( 'id', 'template_name', # 和上面的字段名、类型保持一致 creator_id=Value(None, output_field=IntegerField()), creator_email=Value(None, output_field=CharField(max_length=254)) )
4. 执行合并
现在两个查询集字段完全匹配,就可以正常union了:
combined_qs = company_qs.union(default_qs)
5. 排查SQL语句(可选)
要是还是返回null,打印生成的SQL看看有没有正确JOIN User表:
print(company_qs.query)
如果SQL里没JOIN User表,那得检查CompanyTemplateMessage的creator外键定义是不是写错了,比如有没有指定错误的related_name导致关联异常。
内容的提问来源于stack exchange,提问作者Za Gol
相关产品推荐
相关产品推荐

