Как использовать prefetch_related в отношении ManyToMany с использованием pk selected - PullRequest
1 голос
/ 20 мая 2019

Как отобразить категорию: отношение «многие ко многим», к которой относится фильм, на странице сведений на основе выбранного на странице списка ПК. Я ищу способ сделать это с помощью prefetch_related я возможно. Любой другой способ тоже подойдет.

models.py

class Movie(models.Model):
    title = models.CharField(max_length=70)
    description = models.TextField(max_length=500)

class Category(models.Model):
    name = models.CharField(max_length=70)
    movie = models.ManyToManyField(Movie, related_name='categories')

views.py

class MovieListView(ListView):
    model = Movie
    context_object_name = 'movies'
    template_name = 'snippets/index.html'

    def get_queryset(self):
        return Movie.objects.all()

class MovieDetailView(DetailView):
    model = Movie
    template_name = 'snippets/detail.html'

Любая помощь будет высоко ценится.

1 Ответ

2 голосов
/ 20 мая 2019

Вы можете изменить queryset вашего DetailView на:

class MovieDetailView(DetailView):
    model = Movie
    queryset = Movie.objects<b>.prefetch_related('categories')</b>
    template_name = 'snippets/detail.html'
    <b>context_object_name = 'movie_name'</b>

Здесь вам не нужно ни выполнять фильтрацию, ни устанавливать get_context_data. Вы можете указать имя объекта с атрибутом context_object_name, и DetailView [Django-doc] автоматически отфильтрует первичный ключ, если URL содержит * Параметр 1013 * (а также для slug, указанный в URL-адресе, содержит параметр slug). Документация по get_object [Django-doc] гласит:

Возвращает один объект, который будет отображаться в этом представлении. Если queryset при условии, что queryset будет использоваться в качестве источника объектов; в противном случае будет использоваться get_queryset(). get_object() ищет pk_url_kwarg аргумент в аргументах к представлению; если этот аргумент Этот метод выполняет поиск на основе первичного ключа, используя значение . Если этот аргумент не найден, он ищет slug_url_kwarg и выполняет поиск слагов, используя slug_field.

Когда query_pk_and_slug равен True, get_object() выполнит его поиск с использованием как первичного ключа, так и пули.

Имя movie_name, однако, немного «вводит в заблуждение», так как можно ожидать, что оно имеет дело с именем (str ing), тогда как это объект Movie. Возможно, лучше вместо context_object_name установить 'movie'.

Обратите внимание, что .prefetch_related все равно потребует дополнительного запроса для извлечения связанных категорий в память. Таким образом, использование movie.categories в представлении приведет к тому же количеству запросов.

В шаблоне, например, вы можете отобразить movie с такими категориями, как:

{{ movie }}; categories:
{% for category in movie.categories.all %}
    {{ category }}
{% endfor %}
...