#django #django-models
#django #django-модели
Вопрос:
независимо от того, сколько руководств / документации я прочитал, я все еще не совсем понимаю, как именно я должен использовать prefetch_related.
Мой models.py:
class ProfileComment(models.Model):
author = models.ForeignKey('Profile', on_delete=models.CASCADE, null=True)
date_posted = models.DateTimeField(default=timezone.now, editable=False)
body = models.CharField(max_length=180, blank=True)
...
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
comments = models.ManyToManyField(ProfileComment, related_name='comments', blank=True)
avatar = models.FileField(upload_to=avatar_folder, default='user-avatar/default.png')
...
Мой views.py:
profile = Profile.objects.prefetch_related('comments').get(user=request.user)
И в шаблоне:
{% for comment in profile.comments.all %}
<div>
<p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
<p>Message: {{ comment.body }}</p>
<p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}
Однако, независимо от того, что я добавляю в prefetch_related, количество запросов просто увеличивается примерно на 5 для каждой записи
Комментарии:
1.
Prefetch_related
создаст дополнительные запросы. Для а.get(user=request.user)
это вообще не будет иметь никакого значения.2. Итак, как я могу сделать так, чтобы он не делал еще 10 запросов для 1 записи?
3. В настоящее время у меня есть 10 записей, и для их загрузки требуется 80 запросов
4. вы этого не делаете.
.prefetch_related
выполняет дополнительные запросы для минимизации пропускной способности к базе данных. Если вы хотите получить все комментарии в одном запросе, вы повторяете данные для профиля в каждой записи . Если вы сделаете это для дополнительного отношения, вы повторяете данные профиля, умноженные на количество строк, а данные комментария умножаются на другое отношение.5. это из-за
comment.author.user
части. Это можно оптимизировать с.select_related
помощью .
Ответ №1:
.prefetch_related(…)
[Django-doc] следует использовать для массовой выборки связанных объектов для набора запросов. Поскольку вы пишете:
….get(user=request.user)
однако это не будет иметь никакого значения, поскольку вы извлекаете только один объект, и, таким образом, он будет предварительно выбирать комментарии в дополнительном запросе.
Однако что вы можете свести к минимуму , так это количество дополнительных запросов , которые исходят от comment.author.user
вас . Это приведет к двум дополнительным запросам для каждого комментария, так ForeignKey
как они загружаются лениво.
Таким образом, ваш вид может выглядеть следующим образом:
profile = Profile.objects.get(user=request.user)
comments = profile.comments.select_related('author', 'author__user')
где вы передаете оба profile
и comments
в шаблон, а затем извлекаете его с помощью:
{% for comment in comments %}
<div>
<p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
<p>Message: {{ comment.body }}</p>
<p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}
таким образом, здесь мы читаем комментарии из набора запросов, в котором мы извлекаем профиль и пользователя этого профиля в одном запросе. В результате мы сделаем два запроса: один для Profile
, и один для всех Comment
s , включая .author
и .author.user
.
Комментарии:
1. спасибо, это действительно помогло с путаницей