00:00

文章目录

加载目录中...

FBV与CBV基本介绍

FBV和CBV是Django框架中编写视图的两种主要方式。

FBV——函数式视图

FBVFunction-Based Views 的缩写,即基于函数的视图。这是最直观、最简单的方式,你定义一个Python函数,它接收一个 HttpRequest 对象作为参数,并返回一个 HttpResponse 对象。

示例:

# views.py
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from .models import Article

def article_list(request):
    """显示所有文章列表"""
    if request.method == 'GET':
        articles = Article.objects.all()
        return render(request, 'blog/article_list.html', {'articles': articles})
    else:
        return HttpResponse(status=405)  # 方法不允许

def article_detail(request, pk):
    """显示单篇文章的详情"""
    article = get_object_or_404(Article, pk=pk)
    return render(request, 'blog/article_detail.html', {'article': article})

特点:

  • 简单直接:逻辑清晰,非常适合简单的视图。
  • 显式控制流:使用 if request.method == ‘GET/POST‘ 来显式地处理不同的HTTP方法,一目了然。
  • 装饰器灵活:可以非常方便地使用装饰器来添加功能(如登录验证 @login_required,权限检查 @permission_required)。

CBV——类视图

CBVClass-Based Views 的缩写,即基于类的视图。你将视图定义为一个类,该类继承自Django提供的各种通用视图类。不同的HTTP方法(GET, POST)由类中的不同方法(get(), post())来处理。

我们将实现三个视图:

  1. ArticleListView - 文章列表 (处理GET请求)
  2. ArticleDetailView - 文章详情 (处理GET请求)
  3. ArticleCreateView - 创建文章 (处理GET和POST请求)

1. 最简单的CBV:文章列表视图

首先,你需要让视图类继承Django最基础的 View 类。

# views.py
from django.views import View
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from .models import Article

class ArticleListView(View):
    """处理获取文章列表的类视图"""

    def get(self, request):
        """处理HTTP GET请求"""
        articles = Article.objects.all()
        return render(request, 'blog/article_list.html', {'articles': articles})

URL配置 (urls.py):

from django.urls import path
from .views import ArticleListView

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

关键点

  • 继承自 django.views.View
  • 定义了 get 方法来处理GET请求。
  • urls.py 中,必须使用 .as_view() 方法来将类转换为Django可识别的视图函数。

2. 带参数的路由:文章详情视图

这个视图需要从URL中捕获一个参数(如文章ID)。

# views.py (接上面的代码)
class ArticleDetailView(View):
    """处理获取单篇文章详情的类视图"""

    def get(self, request, pk):
        """处理HTTP GET请求
        pk: 从URL中捕获的参数
        """
        article = get_object_or_404(Article, pk=pk)
        return render(request, 'blog/article_detail.html', {'article': article})

URL配置 (urls.py):

from django.urls import path
from .views import ArticleListView, ArticleDetailView

urlpatterns = [
    path('articles/', ArticleListView.as_view(), name='article-list'),
    path('articles/<int:pk>/', ArticleDetailView.as_view(), name='article-detail'),
]

关键点

  • URL模式中定义了 <int:pk> 参数。
  • 这个参数会直接传递给视图类的 get 方法(以及 post, put 等其他你定义的方法)。

3. 处理多种请求方法:创建文章视图

这个视图需要同时处理GET(显示空表单)和POST(处理表单提交)两种请求。

# views.py (接上面的代码)
from django.shortcuts import redirect

class ArticleCreateView(View):
    """处理创建新文章的类视图"""

    def get(self, request):
        """处理GET请求:显示一个空表单"""
        # 在实际项目中,你可能会使用Django Form或ModelForm
        # 这里为了简单,直接渲染一个模板
        return render(request, 'blog/article_form.html')

    def post(self, request):
        """处理POST请求:接收数据并创建新文章"""
        # 1. 从请求中获取数据
        title = request.POST.get('title')
        content = request.POST.get('content')

        # 2. 简单的数据验证(实际应用中要用Form!)
        if title and content:
            # 3. 创建并保存新文章
            article = Article.objects.create(
                title=title,
                content=content,
                # 通常作者会与当前登录用户关联,这里简单处理
            )
            # 4. 成功后重定向到详情页或其他页面
            return redirect('article-detail', pk=article.pk)
        else:
            # 5. 如果数据无效,返回表单并显示错误
            return render(request, 'blog/article_form.html', {'error': '标题和内容不能为空!'})

URL配置 (urls.py):

urlpatterns = [
    path('articles/new/', ArticleCreateView.as_view(), name='article-create'),
    # ... 其他路径
]

关键点

  • 同一个URL(/articles/new/)根据请求方法(GET/POST)的不同,会由不同的类方法处理。
  • get 方法负责展示页面。
  • post 方法负责处理业务逻辑(创建文章)和重定向。

核心区别对比表

特性 FBV (函数式视图) CBV (类视图)
本质 一个函数 一个类
代码组织 使用 if 语句处理不同HTTP方法 使用独立的类方法(如 get(), post())处理
代码复用 较低,需自己编写所有逻辑 ,通过继承和Mixin复用父类代码
适用场景 简单页面、一次性逻辑、API端点 复杂页面CRUD操作、需要高度复用的场景
可读性 简单逻辑下非常直观 结构更规范,但需要了解类继承体系
装饰器 直接使用 @decorator 需要用到 method_decorator 或将装饰器加到 dispatch 方法上
灵活性 非常灵活,自由度高 框架约束性强,但在框架内扩展性极佳

如何选择?

  • 使用 FBV 当
    • 视图逻辑非常简单。
    • 是一个特殊的、一次性的功能,不太可能在其他地方复用。
    • 你需要非常精细地、非标准地控制流程。
  • 使用 CBV 当
    • 你需要实现标准的CRUD(增删改查)操作。这是CBV最大的优势所在
    • 视图逻辑比较复杂,需要将不同HTTP方法的处理分离开。
    • 你希望代码更结构化、更面向对象。
    • 你希望在多个视图之间复用大量代码。

总结

在现代Django开发中,CBV已经成为主流和最佳实践,因为它能让你用更少的代码做更多的事,尤其适合后台管理系统等大量标准数据操作场景。

FBV并没有被淘汰,它依然在需要高度定制化逻辑或非常简单的情况下发挥着重要作用。很多项目都是 CBV 为主,FBV 为辅 的混合模式。

理解两者的区别和适用场景,能帮助你在合适的场景选择最合适的工具。

返回文章列表

评论区 0