Django generic view动态过滤访问电影详情页报404问题求解
问题原因
你遇到的404错误核心是错误重写了DetailView的get_queryset()方法,破坏了类视图的内置执行逻辑:
- 你给视图配置了
model = Movie,DetailView默认会自动读取URL路径里的pk参数,从Movie表中查询匹配的单条电影记录 - 你重写
get_queryset()时返回的是Show对象的查询集,相当于告诉DetailView要以Show表为数据源,查找主键匹配URL参数的单条记录。此时视图会找id=1的Show记录,找不到自然抛出"No show found matching the query"的404错误 - 你在
get_queryset()里写的self.movie = get_object_or_404(Movie, id=self.kwargs['pk'])属于多余逻辑,DetailView本身已经内置了目标Movie的查询能力,你手动查出来的Movie实例没有接入视图的主流程,哪怕控制台能正常打印关联场次,也解决不了主查询集指向错误表的问题
修正方案
你的URL配置、模型定义均无问题,只需要按以下步骤调整视图代码即可:
- 删除整个错误编写的
get_queryset()方法,不需要手动查询Movie实例,DetailView会自动完成对应电影的查询,查询到的Movie实例会存为视图的self.object属性,也会按照你配置的context_object_name = 'movie'传递到模板上下文 - 调整
get_context_data()方法,通过已查询到的Movie实例获取关联的放映场次即可,不需要重复查询Movie。可以直接使用Django外键自带的反向关联管理器show_set获取关联场次,比手动写filter更简洁
修正后的完整视图代码如下:
from django.views.generic import DetailView from .models import Movie, Show class MovieDetails(DetailView): model = Movie context_object_name = 'movie' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # self.object 就是当前URL匹配到的Movie实例 context['shows_played'] = self.object.show_set.all() return context
修正后访问/movie/1/路径时,视图会先正确查到id=1的Movie记录,再把该电影关联的所有Show数据放到上下文的shows_played变量里,模板中直接遍历这个变量即可渲染所有对应场次,不会再触发404错误。
内容的提问来源于stack exchange,提问作者ragnaut
相关产品推荐
相关产品推荐

