You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 4.0 ListView获取指定Genre多对多关联Book列表方法

实现方案

你的性能判断是正确的:通过关联关系反向查询,和直接过滤Book表关联字段的逻辑,底层都是走数据库JOIN关联查询,不会把全量图书加载到内存遍历,性能远高于循环全表筛选的写法。

先修正两个基础配置问题:

  • 路由里写的<string:name>转换器不符合Django语法,内置路径转换器没有string类型,字符串匹配对应的转换器是str,不改会触发路由配置错误
  • 这个视图要返回的是图书列表,所以model属性应该指定为Book而非Genre,否则默认查询集返回的是分类对象,和你的需求不符

具体代码实现

1. 修正urls.py路由配置

from django.urls import path
from .views import GenreListView

urlpatterns = [
    # 将原有的<string:name>替换为<str:name>,末尾加斜杠符合Django路由规范
    path('genre/<str:name>/', GenreListView.as_view(), name='book-genre'),
]

2. 完善GenreListView视图逻辑

类视图中URL传入的路径参数会存在self.kwargs字典里,先通过参数匹配到对应Genre对象,不存在直接返回404避免程序报错,再通过反向关联拿到对应图书集合;如果需要在模板里展示当前分类信息,额外重写get_context_data把分类对象传入上下文即可。

from django.views.generic import ListView
from django.shortcuts import get_object_or_404
from .models import Book, Genre

class GenreListView(ListView):
    model = Book
    # 替换为你实际的模板路径
    template_name = "book/genre_list.html"
    # 模板中使用的图书列表变量名,默认值为object_list,可自定义
    context_object_name = "book_list"
    # 要开启分页的话直接配置paginate_by即可
    # paginate_by = 20

    def get_queryset(self):
        # 从URL路径中提取分类名称参数
        genre_name = self.kwargs.get("name")
        # 匹配对应分类,不存在直接返回404响应
        self.genre = get_object_or_404(Genre, name=genre_name)
        # 反向查询该分类下所有图书,可链式调用order_by做自定义排序
        return self.genre.book_set.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 把当前分类对象传入模板,用于展示分类名等信息
        context["current_genre"] = self.genre
        return context

补充说明

  • self.genre.book_set.all()和直接写Book.objects.filter(genres__name=genre_name)底层生成的SQL几乎完全一致,都是通过多对多中间表做关联过滤,不会全表扫描Book数据,性能没有差异。
  • 如果后续需要加筛选、排序逻辑,直接在get_queryset返回的查询集上链式调用对应方法即可,ListView自带的分页、上下文注入功能都可以正常使用。
  • 模板中可以直接通过{{ current_genre.name }}展示当前分类名称,用{% for book in book_list %}循环渲染图书条目。

内容的提问来源于stack exchange,提问作者Scrolen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 03:01:26