варианты аргументов '* lookups' для функции 'prefetch_related' - PullRequest
1 голос
/ 04 апреля 2019

Я не могу понять разницу между prefetch_related ('arg_set') и prefetch_related ('arg').

Иногда prefetch_related не работает при использовании аргумента 'arg'even' arg_set '.

Я искал через docs.djangoproject.com, но, по крайней мере, я не могу найти соответствующий документ на обеих страницах ниже. https://docs.djangoproject.com/en/2.1/ref/models/querysets/ https://docs.djangoproject.com/ja/2.1/ref/contrib/contenttypes/

Могут ли некоторые из вас уточнить разницу и когда _set необходимо? И я хочу прочитать официальный документ, связанный с этой проблемой, поэтому, показывая мне, ссылка ссылка приветствуется.

Заранее спасибо.

окружающая среда: windows10, python 3.7.2, django 2.1.8, sqlite3, PyCham 2019.1.

views.py

from django.shortcuts import render
from .models import Article


def index(request):
    a = Article.objects.all().select_related('user').prefetch_related('comment_set').order_by('id')  # [1]
    a = Article.objects.all().select_related('user').prefetch_related('comment').order_by('id')  # [2]

    return render(request,
                  'sns/index.html',
                  {'articles': a})

models.py

from django.db import models
from article_comment_model.settings import AUTH_USER_MODEL


class Article(models.Model):
    user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='article_user')
    title = models.CharField(max_length=100)
    text = models.TextField()


class Comment(models.Model):
    user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='comment_user')
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    text = models.TextField()

Я хочу хорошо понять разнообразие аргументов prefetch_related.

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Имя поиска для использования в prefetch_related зависит от ответа на пару вопросов:

  • Определяется ли отношение в запрашиваемой модели или на другой стороне отношения?

Если отношение определено в запрашиваемой вами модели (так называемые «прямые отношения» в документации Django), то поиск - это просто имя поля . Если отношение определено на другом конце отношения («обратное отношение»), тогда поиск зависит от второго вопроса:

  • Вы определили related_name в другой модели, где определены отношения?

Если да, то поиск будет related_name. Если related_name отсутствует, Django использует имя по умолчанию, которое modelname_set для отношений x-to-many и modelname для отношений x-to-one (оба в нижнем регистре).

На практике это означает следующее в вашем коде:

  • отношение x-ко-многим:
# no related names defined, using default manager name
Article.objects.prefetch_related('comment_set')
# using related names
User.objects.prefetch_related('article_user', 'comment_user')
  • отношения x-to-one:
Article.objects.prefetch_related('user')
Comment.objects.prefetch_related('article', 'user')

Использование prefetch_related для отношений x-to-one, как в последних двух примерах выше, встречается редко. В основном мы используем select_related, так как последний создает соединение только в исходном запросе, а не создает отдельный запрос. Однако, как вы можете прочитать в конце документации , prefetch_related имеет несколько потенциальных преимуществ. Может:

  • получить отфильтрованный набор запросов
  • получить неполные модели (через only и defer)
  • выполнить вложенную предварительную выборку с помощью объекта Prefetch
0 голосов
/ 04 апреля 2019

Аргументом для callig prefetch_related() будет имя отношения. В вашем случае это были бы обратные отношения ForeignKey. Как видно из документации , имя обратной связи будет FOO_set, где FOO - это строчное имя модели.

Поэтому в вашем примере prefetch_related('comment_set') должно быть правильным. Если вы укажете related_name как

article = models.ForeignKey(Article, on_delete=models.CASCADE, 
                            related_name='comments')

вместо FOO_set будет использоваться related_name, поэтому prefetch_related('comments') должен быть действительным в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...