Django关于ListView通用视图的理解(Cursor解释)

发布于:2025-07-22 ⋅ 阅读:(16) ⋅ 点赞:(0)

User

这个是django官方文档上面给出的Listview这个的用法,在现在基础上,如何修改,才可以看到这个的效果呢


Cursor

你现在的 ArticleListView 已经是基于 Django 官方文档的标准写法了,但要“看到效果”,还需要做以下几步:


1. 配置 URL

你需要在 urls.py 中为这个视图配置一个路由。例如:

假设你在 django_app/django_app/urls.py 里:

from django.contrib import admin
from django.urls import path
from app01.views import ArticleListView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', ArticleListView.as_view(), name='article-list'),
]

2. 创建模板

你的 ArticleListView 默认会寻找 app01/article_list.html 这个模板文件。你需要在 django_app/app01/ 目录下创建 article_list.html,内容可以参考:

<!-- django_app/app01/article_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Article List</title>
</head>
<body>
    <h1>Article List</h1>
    <ul>
        {% for article in object_list %}
            <li>{{ article.title }}</li>
        {% empty %}
            <li>No articles found.</li>
        {% endfor %}
    </ul>
    <p>当前时间:{{ now }}</p>
</body>
</html>

3. 确保有 Article 模型和数据

你的 ArticleListView 依赖于 articles.models.Article。你需要确保有这个模型,并且数据库里有数据。否则页面会显示“没有文章”。


4. 启动开发服务器并访问

在项目根目录下运行:

python manage.py runserver

然后在浏览器访问:
http://127.0.0.1:8000/articles/


总结

只要完成上面4步,你就能看到 ListView 的效果了。如果你有分页需求,可以在页面底部加上分页控件(可选)。

如果你有具体报错或页面空白,可以把报错信息发给我,我帮你排查!

from django.contrib import admin
from django.urls import path
from app01.views import ArticleListView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', ArticleListView.as_view(), name='article-list'),
]
<!-- django_app/app01/article_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Article List</title>
</head>
<body>
    <h1>Article List</h1>
    <ul>
        {% for article in object_list %}
            <li>{{ article.title }}</li>
        {% empty %}
            <li>No articles found.</li>
        {% endfor %}
    </ul>
    <p>当前时间:{{ now }}</p>
</body>
</html>
python manage.py runserver

User

但是出现报错[21/Jul/2025 22:29:44] “GET /articles/ HTTP/1.1” 500 88749
Internal Server Error: /articles/
Traceback (most recent call last):
File “E:\miniconda\envs\django_env\Lib\site-packages\django\core\handlers\exception.py”, line 55, in inner onse = response.render()
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File “E:\miniconda\envs\django_env\Lib\site-packages\django\core\handlers\base.py”, line 220, in _get_response
response = response.render()
^^^^^^^^^^^^^^^^^
File “E:\miniconda\envs\django_env\Lib\site-packages\django\template\response.py”, line 114, in render
self.content = self.rendered_content
^^^^^^^^^^^^^^^^^^^^^
File “E:\miniconda\envs\django_env\Lib\site-packages\django\template\response.py”, line 90, in rendered_content
template = self.resolve_template(self.template_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “E:\miniconda\envs\django_env\Lib\site-packages\django\template\response.py”, line 72, in resolve_template
return select_template(template, using=self.using)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “E:\miniconda\envs\django_env\Lib\site-packages\django\template\loader.py”, line 47, in select_template
raise TemplateDoesNotExist(", ".join(template_name_list), chain=chain)
django.template.exceptions.TemplateDoesNotExist: app01/article_list.html 这个是为什么呢


Cursor

你的报错信息:

django.template.exceptions.TemplateDoesNotExist: app01/article_list.html

意思是:Django 在渲染 ArticleListView 时,找不到模板文件 app01/article_list.html


解决方法

你需要在 django_app/app01/ 目录下新建一个文件,名字叫:
article_list.html
注意:文件名必须和 ListView 默认查找的名字一致,且路径要对。


步骤
  1. django_app/app01/ 目录下新建 article_list.html 文件。

  2. 内容可以参考:

<!-- django_app/app01/article_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Article List</title>
</head>
<body>
    <h1>Article List</h1>
    <ul>
        {% for article in object_list %}
            <li>{{ article.title }}</li>
        {% empty %}
            <li>No articles found.</li>
        {% endfor %}
    </ul>
    <p>当前时间:{{ now }}</p>
</body>
</html>

说明
  • 你之前有个 aticle_list.html,但拼写错了(少了个 r),而且你已经删掉了。
  • 正确的名字是:article_list.html(注意拼写和路径)。
  • 文件必须放在 django_app/app01/ 目录下。

完成后

保存文件,刷新页面,就不会再报 TemplateDoesNotExist 了。

如还有问题,欢迎继续提问!

django.template.exceptions.TemplateDoesNotExist: app01/article_list.html
<!-- django_app/app01/article_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Article List</title>
</head>
<body>
    <h1>Article List</h1>
    <ul>
        {% for article in object_list %}
            <li>{{ article.title }}</li>
        {% empty %}
            <li>No articles found.</li>
        {% endfor %}
    </ul>
    <p>当前时间:{{ now }}</p>
</body>
</html>

User

@article_list.html 这个文件不是在这里的吗


Cursor

是的,你现在的 article_list.html 文件路径和内容都是正确的,放在了 django_app/app01/article_list.html,这正是 Django 默认会查找的路径。


可能的原因和排查建议

如果你刚刚新建或修正了文件,但依然报 TemplateDoesNotExist: app01/article_list.html,可能有以下几种原因:

1. 路径没被 Django 识别为模板目录

请检查你的 settings.py 文件中,TEMPLATES 配置项的 DIRSAPP_DIRS

  • APP_DIRS 必须为 True,这样 Django 才会自动在每个 app 的目录下查找 templates 文件夹。
  • 但你现在模板直接放在 app01/ 下,不在 app01/templates/app01/ 下。Django 其实也能找到,但推荐放在 app01/templates/app01/article_list.html,这样更标准。
2. 缓存或服务未重启
  • 如果你是新建的文件,请确保保存了文件,并且重启了开发服务器(有时候 IDE 没有自动保存)。
3. 文件名拼写
  • 再次确认文件名是 article_list.html,不是 aticle_list.html 或其他拼写错误。
4. 项目结构

标准 Django 项目推荐的模板结构如下:

django_app/
  app01/
    templates/
      app01/
        article_list.html

这样 Django 查找模板时更不会出错。


推荐你这样调整

  1. django_app/app01/ 下新建 templates/app01/ 目录。
  2. article_list.html 移动到 django_app/app01/templates/app01/article_list.html
  3. 保证 settings.py 里的 APP_DIRS: True

例子

settings.py 相关部分:

TEMPLATES = [
    {
        # ... 其他配置 ...
        'APP_DIRS': True,
        # ... 其他配置 ...
    },
]

总结

  • 你现在的文件路径是可以的,但更推荐放到 app01/templates/app01/article_list.html
  • 如果还报错,重启开发服务器,确认拼写和路径。
  • 如果还不行,把 settings.py 里的 TEMPLATES 配置贴出来,我帮你具体看。

如有疑问,欢迎继续追问!

django_app/
  app01/
    templates/
      app01/
        article_list.html
TEMPLATES = [
    {
        # ... 其他配置 ...
        'APP_DIRS': True,
        # ... 其他配置 ...
    },
]

User

我这里还是不太理解ListView整体调用逻辑,以及它为啥会调用到article_list.htm来展示数据


Cursor

你的问题非常好!下面我用通俗易懂的方式,详细解释一下 Django 的 ListView 调用逻辑,以及为什么会自动用 article_list.html 这个模板。


1. ListView 的整体调用流程

假设你访问 /articles/,Django 的处理流程大致如下:

  1. URL 路由匹配
    你在 urls.py 里写了:

    path('articles/', ArticleListView.as_view(), name='article-list')
    

    这表示访问 /articles/ 时,会调用 ArticleListView 这个类视图。

  2. ListView 处理请求
    ArticleListView 继承自 Django 的 ListView
    ListView 是一个通用视图,专门用来展示某个模型的“列表页”。

  3. 自动查找数据
    你在视图里写了:

    model = Article
    

    这表示 ListView 会自动帮你查找 Article 这个模型的所有数据(等价于 Article.objects.all()),并传递给模板。

  4. 自动选择模板
    ListView 会自动寻找模板,查找规则如下(假设你的 app 叫 app01,模型叫 Article):

    • 首选:app01/article_list.html
    • 其次:app01/article_list.xml(如果请求是 xml)
    • 你也可以通过 template_name 属性手动指定模板名

    之所以找 article_list.html,是因为:

    • 模型名是 Article
    • 视图类型是“列表”(list)
    • 所以模板名就是 article_list.html
  5. 渲染模板
    ListView 会把查到的数据(默认变量名是 object_listarticle_list)传给模板,然后渲染出页面。


2. 为什么会用 article_list.html

  • Django 的通用视图(如 ListView)有一套命名约定,用来自动查找模板。
  • 约定是:<app_label>/<model_name>_list.html
    • 你的 app 叫 app01
    • 你的模型叫 Article
    • 所以模板名就是 app01/article_list.html
  • 这样做的好处是:不用每次都手动指定模板名,省事!

如果你想用别的模板名,可以在视图里加一行:

class ArticleListView(ListView):
    model = Article
    template_name = "my_custom_template.html"

3. 总结流程图

graph TD
A[用户访问 /articles/] --> B[urls.py 匹配到 ArticleListView]
B --> C[ListView 自动查找 Article 数据]
C --> D[ListView 自动查找 article_list.html 模板]
D --> E[渲染模板并返回页面]

4. 你可以这样理解

  • ListView 就像一个“智能管家”,你只要告诉它“我要展示哪个模型的数据”,它就会自动帮你查数据、找模板、渲染页面。
  • 模板名的查找是有默认规则的,方便开发者快速开发。

如果你还想了解更底层的调用细节,或者想看源码流程,也可以告诉我!

   path('articles/', ArticleListView.as_view(), name='article-list')
   model = Article
class ArticleListView(ListView):
    model = Article
    template_name = "my_custom_template.html"
graph TD
A[用户访问 /articles/] --> B[urls.py 匹配到 ArticleListView]
B --> C[ListView 自动查找 Article 数据]
C --> D[ListView 自动查找 article_list.html 模板]
D --> E[渲染模板并返回页面]

User

当渲染到article_list.html页面的时候里面的object_list now变量是如何确定调用的呢 也是约定好的吗


Cursor

你的问题非常专业!下面详细解释:


1. object_list 变量的来源

(1)Django 的约定

  • ListView 视图中,Django 会自动把查到的所有对象(比如 Article.objects.all())传递给模板。
  • 默认变量名是:
    • object_list(通用名,适用于所有 ListView)
    • 也会有 <model_name>_list,比如 article_list(如果你在模板里用也可以)

这就是为什么你在模板里可以直接用 {% for article in object_list %},而不用自己传递。


(2)源码解释

  • ListView 的父类 MultipleObjectMixin 里有如下代码(伪代码):

    context = {
        'object_list': queryset,
        '<model_name>_list': queryset,
    }
    
  • 所以模板里可以用 object_listarticle_list


2. now 变量的来源

  • 这个变量不是 Django 自动提供的,而是你在视图的 get_context_data 方法里手动加进去的:

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["now"] = timezone.now()
        return context
    
  • 这段代码的意思是:

    • 先调用父类的 get_context_data,拿到默认的 context(里面就有 object_list)。
    • 然后你自己加了一个 now 变量,值是当前时间。
    • 最后返回 context,模板里就能用 {{ now }} 了。

3. 总结

  • object_list 是 Django ListView 自动传递的,是约定好的
  • now 是你自己在视图里加的,不是 Django 默认的。

你可以这样理解

  • object_list:Django 帮你自动准备好,模板里直接用。
  • now:你想加什么变量都可以,只要在 get_context_data 里加到 context 里,模板就能用。

如还想了解更多 context 变量的机制或源码细节,欢迎继续提问!

  context = {
      'object_list': queryset,
      '<model_name>_list': queryset,
  }
  def get_context_data(self, **kwargs):
      context = super().get_context_data(**kwargs)
      context["now"] = timezone.now()
      return context

User

@urls.py 那么这里在url指定的时候path(‘articles/’, ArticleListView.as_view(), name=‘article-list’)的属性起的是什么作用


Cursor

你的问题很棒!下面详细解释一下 path('articles/', ArticleListView.as_view(), name='article-list') 这一行每个参数的作用:


1. 'articles/'

  • 这是URL 路径,表示当用户访问 http://你的域名/articles/ 时,会触发后面的视图处理。
  • 例如:http://127.0.0.1:8000/articles/

2. ArticleListView.as_view()

  • 这是视图函数,用来处理这个 URL 的请求。
  • ArticleListView 是你定义的类视图(基于 ListView)。
  • .as_view() 是 Django 的标准写法,把类视图变成一个可以被调用的“函数视图”。
  • 也就是说,用户访问 /articles/,Django 就会调用 ArticleListView 这个类视图,返回相应的页面。

3. name='article-list'

  • 这是URL 的名字,用于在 Django 项目中反向解析 URL
  • 有了这个名字,你可以在模板或代码里用 url 'article-list'reverse('article-list') 来获取 /articles/ 这个路径,而不用死写字符串。
  • 这样做的好处是:如果以后 URL 改了,只要改这里一处,其他地方不用动。

4. 总结

参数 作用说明
'articles/' 匹配用户访问的 URL 路径
ArticleListView.as_view() 指定处理该 URL 的视图(类视图转为函数视图)
name='article-list' 给这个 URL 路由起个名字,方便项目内引用和反向解析

例子:模板中如何用 name

<a href="{% url 'article-list' %}">文章列表</a>

这样写,如果你以后把 URL 改成 'all-articles/',只要改 urls.py,模板不用动。


如还想了解 Django 路由机制、反向解析等细节,欢迎继续提问!

<a href="{% url 'article-list' %}">文章列表</a>

网站公告

今日签到

点亮在社区的每一天
去签到