当使用Prefetch()的to_attr参数时,Django QuerySet的_prefetched_objects_cache为空

sqserrrh  于 12个月前  发布在  Go
关注(0)|答案(1)|浏览(86)

我正在编写测试来检查Django QuerySet是否预取了它应该预取的内容。我可以通过检查对象的_prefetched_objects_cache属性(via this answer)的内容来做到这一点。但是如果我使用Prefetch()to_attr参数,它就不起作用了。
下面是一个填充该高速缓存的简化示例,不使用to_attr

books = Book.objects.prefetch_related(
    Prefetch(
        "authors",
        queryset=Author.objects.filter(author_type="MAIN"), 
    )
).all()

字符串
然后,我可以在QuerySet中的一个对象上检查_prefetched_objects_cache的内容:

>>> print(books[0]._prefetched_objects_cache)
{'authors': <QuerySet [<Author: Author (ID #1)>]>}


但是,如果我使用to_attr参数:

books = Book.objects.prefetch_related(
    Prefetch(
        "authors",
        queryset=Author.objects.filter(author_type="MAIN"), 
        to_attr="people"  # <-- Added this
    )
).all()


...则_prefetched_objects_cache为空:

>>> print(books[0]._prefetched_objects_cache)
{}


有没有办法检查这个文件是否被预取了?它会去哪里?

q5lcpyga

q5lcpyga1#

to_attr参数与Prefetch一起使用时,预取的对象不再存储在模型示例的_prefetched_objects_cache属性中,而是存储在模型示例本身的to_attr指定的属性中。
在你的例子中,你应该检查你在模型示例上用to_attr指定的属性:

books = Book.objects.prefetch_related(
    Prefetch(
        "authors",
        queryset=Author.objects.filter(author_type="MAIN"), 
        to_attr="people"
    )
).all()

# Now, to check the prefetched objects, use the attribute specified by to_attr
print(books[0].people)

字符串
因此,在本例中,books[0].people应该包含预取的作者。
如果你想检查测试中是否发生了预取,你可以Assertto_attr指定的属性存在于模型示例中,并且包含预期的预取对象:

# Assuming you have a Book instance called book
self.assertTrue(hasattr(book, 'people'))
self.assertEqual(list(book.people), expected_people_list)


通过这种方式,您可以验证预取是否按预期发生,以及预取的对象是否存储在指定的属性中。

相关问题