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
相关产品推荐
相关产品推荐

