Django使用MPTT实现分类报VariableDoesNotExist错误求解
Django MPTT树形分类功能
categories变量找不到报错排查 报错现象
访问路径
/blog/blog_posts/时抛出VariableDoesNotExist异常,错误提示:在上下文[{'True': True, 'False': False, 'None': None}, {}, {}]中查找键categories失败。
核心问题
错误出在views.py中对Django通用类视图ListView的方法使用错误:
ListView的get_queryset()方法仅支持返回模型查询集(QuerySet)对象,不支持返回自定义字典结构- 当前写法将封装了
categories的字典作为get_queryset()返回值,会被ListView当作无效查询集丢弃,根本不会注入模板上下文,因此模板访问categories时会报不存在的错误。
修复方法
二选一即可:
方法1:指定上下文变量名(最简写法)
直接给ListView指定context_object_name属性,不需要重写任何方法,默认就会把全部分类数据传递给模板:
class BlogCategoriesList(generic.ListView): model = Category template_name = 'blog/blog_categories_list.html' # 对应模板中使用的变量名categories context_object_name = 'categories'
如果需要对分类做过滤、排序等操作,再重写get_queryset()即可,注意这个方法只能返回查询集:
def get_queryset(self): # 示例:按名称排序返回所有分类 return Category.objects.all().order_by('name')
方法2:重写上下文传递方法
如果需要给模板传递除了分类列表之外的其他变量,可以重写get_context_data方法:
class BlogCategoriesList(generic.ListView): model = Category template_name = 'blog/blog_categories_list.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['categories'] = Category.objects.all() # 其他要传递的变量继续往context字典里加即可 return context
额外注意事项
- 你的
Category模型中get_absolute_url方法调用了self.slug,但当前模型没有定义slug字段,后续访问分类详情页会抛出属性不存在错误,需要在Category模型中补充slug字段:
class Category(MPTTModel): name = models.CharField(max_length=100, null=True,default=None) # 补充slug字段 slug = models.SlugField(max_length=300, unique=True, null=True) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') # 其余代码保持不变
- 你报错的访问路径是
/blog/blog_posts/,需要确认该路由绑定的视图确实是你编写的BlogCategoriesList,如果该路径是文章列表页,需要在文章列表视图中也传递categories变量,或者编写自定义上下文处理器将分类数据注入所有模板,否则文章页渲染分类树时依然会报相同错误。
内容的提问来源于stack exchange,提问作者Arnold Schwartzkopf
相关产品推荐
相关产品推荐

