Django关联查询过滤器能否引用父模型字段值?
Django ORM 查询:筛选存在过期培训记录的Training模型
问题背景
现有两个Django模型:Training(培训)和TrainingAssignment(培训完成记录)。管理员可动态修改Training.days_valid字段调整培训有效期,为满足审计需求,不修改TrainingAssignment的过期日期,需实时计算并查询所有存在已完成培训记录 + 培训有效期 ≤ 当前日期的Training记录。
模型定义:
class Training(models.Model): title = models.CharField(max_length=200) days_valid = models.IntegerField() class TrainingAssignment(models.Model): training = models.ForeignKey( Training, on_delete=models.CASCADE, related_name='training_assignments', blank=True, null=True ) date_started = models.DateTimeField(null=True,blank=True) date_completed = models.DateTimeField(null=True, blank=True) date_expires = models.DateTimeField(null=True, blank=True)
原尝试代码报错training_assignments__training.days_valid is undefined,原因是无法在Python的timedelta中直接引用ORM模型字段,必须使用Django ORM支持的字段间计算方式。
解决方案
Django ORM支持通过F()表达式引用模型字段,实现数据库层面的字段运算。将需求转化为培训完成日期 ≤ 当前日期 - 培训有效期,直接在数据库中完成计算,无需修改现有记录。
基础查询(所有用户的过期培训)
from django.db.models import F from django.utils import timezone now = timezone.now().date() # 筛选存在至少一条已过期培训记录的Training trainings = Training.objects.filter( # 排除未完成的培训记录 training_assignments__date_completed__isnull=False, # 核心条件:完成日期 ≤ 当前日期 - 有效期天数 training_assignments__date_completed__lte=now - F('days_valid') )
针对特定用户的查询(可选)
如果需要筛选当前登录用户的过期培训,只需添加用户过滤条件(假设TrainingAssignment包含user外键字段):
trainings = Training.objects.filter( training_assignments__user=request.user, training_assignments__date_completed__isnull=False, training_assignments__date_completed__lte=now - F('days_valid') )
说明
F('days_valid')直接引用Training模型的days_valid字段值,由数据库执行计算,确保结果实时反映管理员修改的有效期配置。- 该查询无需修改
TrainingAssignment的date_expires字段,所有历史完成记录保持不变,完全满足审计需求。
内容的提问来源于stack exchange,提问作者Martin Noah
相关产品推荐
相关产品推荐

