【问题标题】:How to use prefetch_related in a ManyToMany relation using pk selected如何使用 pk selected 在多对多关系中使用 prefetch_related
【发布时间】:2019-05-19 22:37:55
【问题描述】:

如何根据在列表页面上选择的 pk 在详细信息页面中显示电影所属的类别:多对多关系。我正在寻找一种使用 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'

任何帮助将不胜感激。

【问题讨论】:

  • 您的 get_context_data 方法毫无意义。 DetailView 已经为您获取了对象,这就是重点。

标签: python django django-queryset python-3.6 django-class-based-views


【解决方案1】:

您可以将DetailViewqueryset 更改为:

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

这里不需要做过滤,也不需要设置get_context_data。您可以使用 context_object_name 属性指定对象的名称,如果 url 包含 pk 参数,DetailView [Django-doc] 将自动过滤主键(以及在 slug 上,因为 url 包含slug 参数)。 documentation on get_object [Django-doc] 说:

返回此视图将显示的单个对象。如果queryset 提供,queryset 将用作对象的来源; 否则,将使用get_queryset()get_object() 寻找 pk_url_kwarg 视图参数中的参数;如果这个论点 找到,此方法使用该方法执行基于主键的查找 值。如果没有找到这个参数,它会寻找一个 slug_url_kwarg 参数,并使用 slug_field.

query_pk_and_slugTrue 时,get_object() 将执行其 使用主键和 slug 进行查找。

然而,名称movie_name 有点“误导”,因为人们可能认为这涉及名称(string),而这是Movie 对象。或许将context_object_name 设置为'movie' 会更好。

请注意,.prefetch_related 仍然需要额外的查询才能将相关类别提取到内存中。所以在视图中使用movie.categories,会产生相同数量的查询。

在模板中,您可以例如使用以下类别渲染movie

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

【讨论】:

  • 谢谢。我想要实现的是显示电影所属类别的名称以及电影的名称。您的回答只显示电影的名称。您能帮忙吗?
  • @CurtisBanks:在模板中,您遍历类别,例如{% for category in movie_name %}{{ category }}{% endfor %}(请重命名为movie)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 2019-09-11
相关资源
最近更新 更多