英文:
The difference between prefetch_related and model_set in Djnago
问题
我想知道在我需要检索外键模型对象时,最佳的流程是什么。
<br/>在views.py中使用**prefetch_related**是否是一个选择:
```python
queryset = queryset.prefetch_related('book_set')
context={objects:queryset}
或者直接在模板中使用model_set:
{% for attach in objects.book_set.all %}
哪个更好,哪一个对性能更好?
<details>
<summary>英文:</summary>
I wonder what is the best flow when I need to retrieve foreign key model objects.
========
<br/>is it to use **prefetch_related** in views.py like:
queryset = queryset.prefetch_related('book_set')
context={objects:queryset}
or to use directly in the template by **model_set**:
{% for attach in objects.book_set.all %}
what is better and which one is good for performance?
</details>
# 答案1
**得分**: 1
在Django中,[prefetch_related][1]用于提前选择所有父对象的所有相关对象,主要与`ManyToMany`字段和反向关系一起使用。
而[model_set][2]用于获取单个父对象的所有相关对象,这将明显增加数据库的访问次数。
因此,最好使用`prefetch_related`,因为它将显著减少数据库的访问次数。
如果您不进行反向关系并且具有外键关系,那么首选使用[select_related][3]。
就在模板或视图中编写查询而言,我建议始终在视图中执行所有查询,因为模板会增加额外的开销。
[1]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#prefetch-related
[2]: https://docs.djangoproject.com/en/4.0/topics/db/queries/#related-objects
[3]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#select-related
<details>
<summary>英文:</summary>
In Django [prefetch_related][1] is used to select all related objects for all parent objects in advance mostly used with `ManyToMany` field and a reverse relationship.
While as [model_set][2] is used to get all related objects of a single parent object which will definitely have more database hits.
Hence it is better to do `prefetch_related` as it will reduced the database hits significantly.
If you are not doing reverse relationship and have foreign key relation then [select_related][3] is prefered.
As far as writting queries in template or views is better. I would suggest always do all queries in the view as templates add extra level of overhead.
[1]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#prefetch-related
[2]: https://docs.djangoproject.com/en/4.0/topics/db/queries/#related-objects
[3]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#select-related
</details>
# 答案2
**得分**: 0
最佳方法取决于您的具体用例以及数据库的内容和大小。但一般来说,在``views.py``中使用`prefetch_related`可以通过减少数据库查询来提供更好的性能。
以下是一个示例,用于澄清这两种方法:
1. 在views.py中使用`prefetch_related()`:
```python
# views.py
queryset = Book.objects.all().prefetch_related('author')
context = {'books': queryset}
<!-- template.html -->
{% for book in books %}
{{ book.title }} by {{ book.author.name }}
{% endfor %}
在这种方法中,prefetch_related('author')
会在单个查询中获取所有相关的作者,从而减少了数据库查询次数。
- 在模板中使用
model_set
:
<!-- template.html -->
{% for book in books %}
{{ book.title }} by
{% for author in book.author_set.all %}
{{ author.name }}
{% endfor %}
{% endfor %}
而在第二种方法中,每次迭代book.author_set.all
都会访问数据库以检索相关的作者对象。这可能会导致多次数据库查询,并且可能会出现各种问题,特别是如果您有大量的书籍。
英文:
The best approach depends on your specific use case and the content and size of your database. However, generally using prefetch_related
in the views.py
can provide better performance by reducing database queries.
Here's an example to clarify both approaches:
- Using
prefetch_related()
in views.py:
# views.py
queryset = Book.objects.all().prefetch_related('author')
context = {'books': queryset}
<!-- template.html -->
{% for book in books %}
{{ book.title }} by {{ book.author.name }}
{% endfor %}
In this approach, the prefetch_related('author')
fetches all related authors in a single query, reducing the number of database hits.
- Using
model_set
in the template:
<!-- template.html -->
{% for book in books %}
{{ book.title }} by
{% for author in book.author_set.all %}
{{ author.name }}
{% endfor %}
{% endfor %}
While on the second approach, each iteration of book.author_set.all
hits the database to retrieve the related author object. This can result in multiple database queries, and different sort of problems, especially if you have a large number of books.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论