Django 视图 – FBV 与 CBV(保姆级教程)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

Django 视图:FBV 与 CBV 的深度解析

前言

在 Django 开发中,视图(View)是连接 URL 请求与业务逻辑的核心组件。对于刚接触框架的开发者来说,如何高效组织视图代码是一个关键问题。函数视图(Function-Based Views, FBV)与类视图(Class-Based Views, CBV)是 Django 提供的两种实现方式。本文将通过对比、示例和场景分析,帮助读者理解这两种模式的优缺点,并在实践中选择最适合的方案。


FBV 与 CBV 的基本概念

函数视图(FBV)

FBV 是 Django 最基础的视图形式,通过 Python 函数直接处理请求和响应。其核心逻辑是:接收 HTTP 请求对象,返回 HTTP 响应对象。例如,一个简单的“Hello World”视图可以这样编写:

from django.http import HttpResponse

def hello_world(request):
    return HttpResponse("Hello, World!")

特点

  • 灵活自由:开发者完全掌控代码结构,适合小型功能或快速原型开发。
  • 直观简洁:代码直接映射到 HTTP 请求的处理流程,学习成本较低。

类视图(CBV)

CBV 将视图逻辑封装为 Python 类,通过继承 Django 内置的基类(如 View)实现功能。例如,上述“Hello World”用 CBV 实现如下:

from django.views import View
from django.http import HttpResponse

class HelloWorldView(View):
    def get(self, request):
        return HttpResponse("Hello, World!")

特点

  • 结构化设计:通过类的方法(如 get()post())分离不同 HTTP 方法的逻辑。
  • 复用性强:通过继承和 Mixin(混合类)实现代码复用,适合大型项目。

FBV 与 CBV 的核心差异

1. 代码组织方式

  • FBV:以函数为单位,每个函数对应一个 URL 路径的逻辑。
    # urls.py 中的 FBV 配置示例
    path("hello-fbv/", hello_world),
    
  • CBV:以类为单位,通过 as_view() 方法将类转换为可调用视图。
    # urls.py 中的 CBV 配置示例
    path("hello-cbv/", HelloWorldView.as_view()),
    

2. HTTP 方法处理

FBV 需要手动检查 request.method 来区分 GET/POST 等请求:

def user_login(request):
    if request.method == "POST":
        # 处理表单提交
    else:
        # 渲染登录页面
    return render(request, "login.html")

而 CBV 通过类方法直接绑定 HTTP 方法:

class UserLoginView(View):
    def get(self, request):
        # 渲染登录页面
        return render(request, "login.html")
    
    def post(self, request):
        # 处理表单提交
        return redirect("home")

3. 扩展性与复用性

CBV 的优势在于通过继承和组合实现代码复用。例如,Django 提供了 ListViewDetailView 等通用类视图,可以快速实现对数据库模型的增删改查。

示例:使用 ListView 显示文章列表

from django.views.generic import ListView
from .models import Article

class ArticleListView(ListView):
    model = Article  # 自动关联模型
    template_name = "articles/list.html"  # 指定模板路径

而 FBV 需要手动编写查询逻辑:

def article_list(request):
    articles = Article.objects.all()
    return render(request, "articles/list.html", {"articles": articles})

实际场景对比:表单处理案例

场景描述

假设需要实现一个用户注册功能,包含以下步骤:

  1. GET 请求时显示注册表单;
  2. POST 请求时验证数据并保存用户。

FBV 实现

from django.shortcuts import render, redirect
from .forms import RegisterForm

def register(request):
    if request.method == "POST":
        form = RegisterForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect("login")
    else:
        form = RegisterForm()
    return render(request, "users/register.html", {"form": form})

优点:代码逻辑一目了然,适合小型功能。
缺点:若需扩展(如添加重定向逻辑或权限验证),代码可能逐渐冗余。

CBV 实现

from django.views.generic.edit import FormView
from .forms import RegisterForm

class RegisterView(FormView):
    template_name = "users/register.html"
    form_class = RegisterForm
    success_url = "/login/"
    
    def form_valid(self, form):
        form.save()
        return super().form_valid(form)

优点:通过继承 FormView 自动处理表单的 GET/POST 流程,代码更简洁。
缺点:需要理解类视图的生命周期(如 form_valid() 方法的作用)。


如何选择 FBV 或 CBV?

1. 选择 FBV 的场景

  • 简单功能:如单页面展示或少量逻辑的 API 接口。
  • 快速开发:适合对 Django 类视图不熟悉的开发者,或需要快速验证功能时。
  • 特殊需求:某些场景需要完全自定义逻辑(如非标准 HTTP 方法或异步处理)。

2. 选择 CBV 的场景

  • 复杂业务:需要处理多步骤流程(如表单验证、分页、权限控制)时,CBV 的结构化设计更清晰。
  • 代码复用:通过继承 ListViewCreateView 等通用类视图,减少重复代码。
  • 团队协作:类视图的规范性有助于多人协作开发,降低维护成本。

3. 混合使用策略

在实际项目中,两种模式可以结合使用。例如:

  • 用 CBV 处理通用逻辑(如列表页、详情页),
  • 用 FBV 实现特定功能(如第三方 API 的回调接口)。

进阶技巧:扩展 CBV 的能力

1. 自定义基类

通过继承 View 或其他通用类视图,可以创建自己的基类,集中处理公共逻辑:

from django.views import View

class BaseView(View):
    def dispatch(self, request, *args, **kwargs):
        # 添加权限验证或日志记录
        return super().dispatch(request, *args, **kwargs)

class SecureView(BaseView):
    def get(self, request):
        return HttpResponse("Protected Content")

2. 使用 Mixin 混合功能

通过 Mixin(混合类)将功能模块化:

class LoginRequiredMixin:
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return redirect("login")
        return super().dispatch(request, *args, **kwargs)

class ProfileView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, "profile.html")

3. 覆盖生命周期方法

CBV 的 dispatch()get()post() 等方法均可被覆盖,以实现定制化行为:

class CustomListView(ListView):
    def get_queryset(self):
        # 动态过滤查询结果
        return Article.objects.filter(author=self.request.user)

结论

Django 的 FBV 与 CBV 各有适用场景,选择的关键在于项目规模、团队习惯和功能复杂度。对于初学者,FBV 是快速上手的起点;随着项目复杂度提升,CBV 的结构化优势将更加明显。建议在实践中逐步探索两者的结合方式,并通过阅读 Django 官方文档(如 Class-based Views )深化理解。

掌握这两种视图模式后,开发者可以更灵活地应对各类 Web 开发需求,同时为团队协作和代码维护打下坚实基础。

最新发布