Skip to content

Django - 通用视图

编写视图(view)有时会涉及重复的样板代码(boilerplate code),特别是在处理常见任务时,如显示对象列表、显示单个对象的详细信息或处理简单表单。Django 的通用视图(generic views,它们是基于类的视图,简称 CBVs)为这些常见模式提供了预构建的解决方案,让你可以少写代码。

通用视图是位于 django.views.generic 中的 Python 类。你通常可以在 URLconf 中直接使用它们,或者在 views.py 文件中继承它们以定制其行为。

  • 显示视图:
  • TemplateView:渲染给定的模板,可包含可选的上下文(context)。
  • ListView:渲染对象列表(通常来自数据库查询)。
  • DetailView:渲染单个对象的详细信息。
  • 编辑视图:
  • FormView:渲染和处理表单。
  • CreateView:显示用于创建新对象的表单并处理保存。
  • UpdateView:显示用于编辑现有对象的表单并处理保存。
  • DeleteView:显示确认页面并处理删除现有对象。
  • 基于日期的视图: (ArchiveIndexView, YearArchiveView, MonthArchiveView 等),用于显示基于日期的对象。

示例 1:显示静态页面(TemplateView)

Section titled “示例 1:显示静态页面(TemplateView)”

假设你有一个简单的 about.html 模板要显示。

方法 1:直接在 urls.py 中使用

myapp/urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('about/',
TemplateView.as_view(template_name='myapp/about.html'),
name='about'),
# ... other URLs
]

方法 2:在 views.py 中继承(如果你需要添加额外的上下文,这将非常有用)

myapp/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = 'myapp/about.html'
# Optional: Add extra context data
# 可选:添加额外的上下文数据
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['page_title'] = 'About Us'
return context
myapp/urls.py
from django.urls import path
from .views import AboutView
urlpatterns = [
path('about/', AboutView.as_view(), name='about'),
# ... other URLs
]

在上面两种情况下,访问 /myapp/about/ 都将渲染 myapp/templates/myapp/about.html 模板。

让我们列出假设的 Article 模型中的所有条目。

# myapp/models.py (Hypothetical)
# myapp/models.py (假设)
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', kwargs={'pk': self.pk})

使用 ListView:

myapp/views.py
from django.views.generic import ListView
from .models import Article
class ArticleListView(ListView):
model = Article # Specify the model to list
# 指定要列出的模型
template_name = 'myapp/article_list.html' # Optional: Defaults to myapp/article_list.html
# 可选:模板名称 (默认为 myapp/article_list.html)
context_object_name = 'articles' # Optional: Name in template context (default: object_list)
# 可选:在模板上下文中的变量名 (默认为 object_list)
ordering = ['-pub_date'] # Optional: Order the results
# 可选:结果排序
paginate_by = 5 # Optional: Enable pagination
# 可选:启用分页,每页显示 5 个
myapp/urls.py
from django.urls import path
from .views import ArticleListView
urlpatterns = [
path('articles/', ArticleListView.as_view(), name='article_list'),
# ... other URLs like article_detail
# ... 其他 URL,例如 article_detail
]

模板(myapp/templates/myapp/article_list.html):

myapp/templates/myapp/article_list.html
<!-- myapp/templates/myapp/article_list.html -->
<h1>Articles</h1>
<ul>
{% for article in articles %} {# Use context_object_name here #}
{# 在这里使用 context_object_name #}
<li>
<a href="{{ article.get_absolute_url }}">{{ article.title }}</a>
(Published: {{ article.pub_date|date:"Y-m-d" }})
(发布日期:{{ article.pub_date|date:"Y-m-d" }})
</li>
{% empty %}
<li>No articles have been published yet.</li>
<li>暂无已发布的文章。</li>
{% endfor %}
</ul>
{# Add pagination controls if using paginate_by #}
{# 如果使用了 paginate_by,添加分页控件 #}
{% if is_paginated %}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">&laquo; first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
第 {{ page_obj.number }} 页,共 {{ page_obj.paginator.num_pages }} 页。
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
{% endif %}
</span>
</div>
{% endif %}

访问 /myapp/articles/ 将显示按发布日期排序的、带分页的文章列表。

通用视图显著减少了常见任务所需的代码量,促进了 DRY(Don’t Repeat Yourself,不要重复自己)原则的应用并加快了开发速度。有关更多详情和定制选项,请参阅 Django 关于基于类的视图的文档。