问题描述
我正在使用 Django 3.1 ORM 并且正在运行(使用 pytest
)一个涉及复杂嵌套查询的测试。我遇到了这个失败:
self = <django.db.models.expressions.Subquery object at 0x0000027CE184D2B0>
lookup = 'lte'
def get_lookup(self,lookup):
> return self.output_field.get_lookup(lookup)
E TypeError: get_lookup() missing 1 required positional argument: 'lookup_name'
要调用的 get_lookup(lookup)
在 django.db.models.query_utils.RegisterLookupMixin
中定义为(据我所知)
def get_lookup(self,lookup_name):
...
我的测试对应的源语句涉及到类似
value = Now() - OuterRef(OuterRef('myattr2')) * timedelta(days=1)
queryset2.annotate(has_x=Exists(queryset.filter(myattr__lte=value)))
还有更多的查询构造代码。
我的调试器告诉我 self.output_field
是一个 DateTimeField
对象。
总体来说:
- 上下文是一个
Exists
子查询。 - 查找是
'lte'
(如预期)。 - 该调用提供
DateTimeField
作为self
(来自output_field
)和'lte'
作为lookup_name
。 - 要调用的方法需要
self
和lookup_name
。
呼叫应该有效,不是吗?TypeError
在哪里?
解决方法
@AlexandrTatarinov 的评论是正确的;那也是我的问题; myattr
是这样创建的计算属性:
annotate(myattr=Subquery(queryset3,output_field=DateTimeField))
但出于某种原因,Django 坚定地想要输出字段的字段实例,而不是字段类。
所以 output_field=DateTimeField()
有效,但我的 output_field=DateTimeField
无效。
添加括号,我的问题就解决了。
具有讽刺意味的是,在这种情况下甚至不需要 output_field=
!删除它和添加括号一样有效。
反思我的工作过程,这些是我的错误:
- 我在调试器中检查了正确的
self
是否存在——但显然不够仔细,将DateTimeField
类误认为是DateTimeField
实例。 - 我在调试以前的问题时插入了
output_field=DateTimeField
子句,但在没有帮助时没有再次取出它。坏主意。 - 当我写下我的问题时,当我写下“我的调试器告诉我
self.output_field
是一个DateTimeField
对象。” 并问自己 “Do我知道它是一个DateTimeField
对象而不是DateTimeField
类?”,但我没有再去调试器中查看,我只记得我已经检查过它并且已经很满意。
所以我带回家的课程是:
- (来自第 2 点):不要做半生不熟的事情。
- (来自数字 1 和 3):尽可能少相信自己。