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

DRF过滤查询报'todo__test' is not defined错误解决

报错根因与修复方案

两个核心错误点

  • 语法错误:Django ORM的filter()方法接收的筛选条件是关键字参数格式,必须用=传值,你写的todo__test == test_id是Python布尔判断表达式,根本不是合法的筛选参数,会直接被解析成位置参数触发报错。
  • 字段名逻辑完全错误:你混淆了跨关联查询的字段路径规则。

Django ORM双下划线查询规则说明

Django里跨关联表的筛选字段统一用__(双下划线)拼接路径,规则非常简单:

从你当前正在查询的模型出发,顺着模型上定义的关联字段名,一层层指向最终要匹配的目标字段即可。

你之前看到文档里的purchaser__username例子,逻辑是:查询的目标模型是「订单」,订单模型上定义了名为purchaser的外键字段关联到用户模型,用户模型上有username字段,所以筛选“购买者用户名是xx的订单”时,才会写filter(purchaser__username=xx)。

回到你的场景:
你当前直接查询的就是Todo模型,Todo模型本身就定义了名为test的外键关联Test模型,Django会自动为外键字段生成外键名_id的数据库字段(存关联的主键值),根本不需要加什么todo__前缀——Todo模型上根本没有叫todo的关联字段,当然会报字段不存在。

你之前尝试的几种写法问题也很明确:

  • todo__test:当前查询的是Todo表,表内无todo字段,直接触发不存在报错
  • Todo.test.test_id、Todo.test:这是Python类属性访问语法,filter方法只接受字符串格式的字段路径参数,不支持类名点属性的写法

修复后代码

直接把get_queryset方法里的筛选逻辑改成如下即可:

class TodoList(generics.ListAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

    def get_queryset(self):
        test_id = self.kwargs['test_id']
        return Todo.objects.filter(test_id=test_id)

class Todo(models.Model):
    test = models.ForeignKey(Test, on_delete=models.CASCADE)
    content = models.TextField(blank=True)
    order = models.IntegerField()

    def __str__(self):
        return self.content + ' - ' + self.test.test_name

    class Meta:
        ordering = ['test_id']

补充:如果你后续需要通过关联Test模型的其他字段筛选Todo,比如筛选Test名称为某个值的Todo,才需要用双下划线跨表,写法是test__test_name=xxx,第一个test是Todo上的外键字段名,双下划线后接Test模型上的目标字段名即可。

内容的提问来源于stack exchange,提问作者djo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 11:01:23