51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

prefetch_related和model_set在Django中的区别。

英文:

The difference between prefetch_related and model_set in Djnago

问题 {#heading}

我想知道在我需要检索外键模型对象时,最佳的流程是什么。

<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.
=================================================================================


`&lt;br/&gt;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中,https://docs.djangoproject.com/en/4.2/ref/models/querysets#prefetch-related用于提前选择所有父对象的所有相关对象,主要与`ManyToMany`字段和反向关系一起使用。


而https://docs.djangoproject.com/en/4.0/topics/db/queries#related-objects用于获取单个父对象的所有相关对象,这将明显增加数据库的访问次数。


因此,最好使用`prefetch_related`,因为它将显著减少数据库的访问次数。


如果您不进行反向关系并且具有外键关系,那么首选使用https://docs.djangoproject.com/en/4.2/ref/models/querysets#select-related。


就在模板或视图中编写查询而言,我建议始终在视图中执行所有查询,因为模板会增加额外的开销。


\<details\>
\<summary\>英文:\</summary\>


In Django https://docs.djangoproject.com/en/4.2/ref/models/querysets#prefetch-related is used to select all related objects for all parent objects in advance mostly used with `ManyToMany` field and a reverse relationship.


While as https://docs.djangoproject.com/en/4.0/topics/db/queries#related-objects 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 https://docs.djangoproject.com/en/4.2/ref/models/querysets#select-related 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.


\</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}
</code></pre>
 <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span><span style="color:#75715e">&lt;!-- template.html --&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{% for book in books %}
</span></span><span style="display:flex;"><span>    {{ book.title }} by {{ book.author.name }}
</span></span><span style="display:flex;"><span>{% endfor %}
</span></span></code></pre>
 <p>在这种方法中,<code>prefetch_related('author')</code>会在单个查询中获取所有相关的作者,从而减少了数据库查询次数。</p>
 <ol start="2">
  <li>在模板中使用<code>model_set</code>:</li>
 </ol>
 <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span><span style="color:#75715e">&lt;!-- template.html --&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{% for book in books %}
</span></span><span style="display:flex;"><span>    {{ book.title }} by
</span></span><span style="display:flex;"><span>    {% for author in book.author_set.all %}
</span></span><span style="display:flex;"><span>        {{ author.name }}
</span></span><span style="display:flex;"><span>    {% endfor %}
</span></span><span style="display:flex;"><span>{% endfor %}
</span></span></code></pre>
 <p>而在第二种方法中,每次迭代<code>book.author_set.all</code>都会访问数据库以检索相关的作者对象。这可能会导致多次数据库查询,并且可能会出现各种问题,特别是如果您有大量的书籍。</p>
 <details>
  <summary>英文:</summary>
  <p>The best approach depends on your specific use case and the content and size of your database. However, generally using <code>prefetch_related</code> in the <code>views.py</code> can provide better performance by reducing database queries.</p>
  <p>Here's an example to clarify both approaches:</p>
  <ol>
   <li>Using <code>prefetch_related()</code> in views.py:</li>
  </ol>
  <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span><span style="color:#75715e"># views.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>queryset <span style="color:#f92672">=</span> Book<span style="color:#f92672">.</span>objects<span style="color:#f92672">.</span>all()<span style="color:#f92672">.</span>prefetch_related(<span style="color:#f92672">&amp;</span><span style="color:#75715e">#39;author&amp;#39;)</span>
</span></span><span style="display:flex;"><span>context <span style="color:#f92672">=</span> {<span style="color:#f92672">&amp;</span><span style="color:#75715e">#39;books&amp;#39;: queryset}</span>
</span></span></code></pre>
  <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span>&amp;lt;!-- template.html --&amp;gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{% for book in books %}
</span></span><span style="display:flex;"><span>    {{ book.title }} by {{ book.author.name }}
</span></span><span style="display:flex;"><span>{% endfor %}
</span></span></code></pre>
  <p>In this approach, the <code>prefetch_related(&amp;#39;author&amp;#39;)</code> fetches all related authors in a single query, reducing the number of database hits.</p>
  <ol start="2">
   <li>Using <code>model_set</code> in the template:</li>
  </ol>
  <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span>&amp;lt;!-- template.html --&amp;gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{% for book in books %}
</span></span><span style="display:flex;"><span>    {{ book.title }} by
</span></span><span style="display:flex;"><span>    {% for author in book.author_set.all %}
</span></span><span style="display:flex;"><span>        {{ author.name }}
</span></span><span style="display:flex;"><span>    {% endfor %}
</span></span><span style="display:flex;"><span>{% endfor %}
</span></span></code></pre>
  <p>While on the second approach, each iteration of <code>book.author_set.all</code> 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.</p>
 </details>
 <p></p>
</div>

```
赞(0)
未经允许不得转载:工具盒子 » prefetch_related和model_set在Django中的区别。