R / Richie全部文章 ↑

Python · 1 分钟阅读

通用类视图

Django 为常见场景预制了高度可复用的视图基类:少写代码,多做对的事。

TemplateView

只渲染模板的场景:

from django.views.generic import TemplateView

class IndexView(TemplateView):
    template_name = "post/index.html"

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["hello"] = "Hello Django"
        return ctx
path("index/", IndexView.as_view())

RedirectView

from django.views.generic import RedirectView

class TopicRedirect(RedirectView):
    pattern_name = "post:topic_detail"
    permanent = False           # True 即 301
    query_string = True         # 保留原 URL 查询参数

ListView

from django.views.generic import ListView
from post.models import Topic

class TopicListView(ListView):
    model = Topic
    template_name = "post/topic_list.html"   # 默认 <app>/<model>_list.html
    context_object_name = "topics"           # 默认 <model>_list
    paginate_by = 20
    ordering = ("-created_time",)

模板里:

{% for topic in topics %}
  {{ topic.title }}
{% endfor %}

{% if is_paginated %}
  {% if page_obj.has_previous %}<a href="?page={{ page_obj.previous_page_number }}">上一页</a>{% endif %}
{% endif %}

DetailView

from django.views.generic import DetailView

class TopicDetailView(DetailView):
    model = Topic
    context_object_name = "topic"

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["comments"] = self.object.comments.order_by("-created_time")
        return ctx
path("topic/<int:pk>/", TopicDetailView.as_view(), name="topic_detail")

模板默认名:<app>/<model>_detail.html。

CreateView / UpdateView / DeleteView

from django.urls import reverse_lazy
from django.views.generic import CreateView, UpdateView, DeleteView
from post.models import Topic

class TopicCreateView(LoginRequiredMixin, CreateView):
    model = Topic
    fields = ("title", "content")
    success_url = reverse_lazy("post:topic_list")

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

何时选 FBV / CBV?

场景 建议
简单表单 / API 端点 FBV + DRF
标准 CRUD CBV(ListView / DetailView / CreateView)
复杂业务流、组合多个步骤 FBV 或 CBV + Service 层
需要 Mixin 复用 CBV