You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:25:18