Django新手求助:反向关联外键后如何过滤子模型属性查询集?
解决Django中父对象基于子对象字段比较统计的问题
嘿,我来帮你搞定这个问题!你遇到的global variable score_2 unknown错误,根源在于Django ORM的使用方式——你直接在filter里写score_1__gt=score_2时,Python会把score_2当成一个全局变量,而不是Child模型里的字段。要让ORM知道你是在比较同一个子对象的两个字段,得用Django提供的F()表达式。
具体修改步骤:
- 导入F表达式:在你的models文件顶部或者方法内部导入
F:
from django.db.models import F
- 修正filter语句:把原来的过滤代码改成用
F('score_2')引用字段:
one_better = childs_of_me.filter(score_1__gt=F('score_2'))
- 别忘了保存修改:你的
foo方法里修改了self.winner,最后要调用self.save()才能把更新同步到数据库。
优化后的完整代码:
from django.db import models from django.db.models import F class Parent(models.Model): winner = models.IntegerField(default=0) def foo(self): childs_of_me = self.child_set.all() number_childs = childs_of_me.count() # 使用F表达式比较子对象的两个字段 one_better = childs_of_me.filter(score_1__gt=F('score_2')) one_wins_count = one_better.count() if number_childs > 0 and one_wins_count > number_childs / 2: self.winner = 1 self.save() # 保存更新到数据库 class Child(models.Model): parent = models.ForeignKey(Parent, on_delete=models.CASCADE) score_1 = models.IntegerField(default=0) score_2 = models.IntegerField(default=0)
额外优化建议:
你还可以简化代码,不用先获取所有子对象再过滤,直接链式调用更高效:
def foo(self): one_wins_count = self.child_set.filter(score_1__gt=F('score_2')).count() number_childs = self.child_set.count() if number_childs > 0 and one_wins_count > number_childs / 2: self.winner = 1 self.save()
这样修改后,ORM会在数据库层面完成字段比较和统计,既解决了变量未定义的错误,也让查询更高效。
内容的提问来源于stack exchange,提问作者Kishan
相关产品推荐
相关产品推荐

