FBV和CBV是Django框架中编写视图的两种主要方式。
FBV——函数式视图
FBV 是 Function-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——类视图
CBV 是 Class-Based Views 的缩写,即基于类的视图。你将视图定义为一个类,该类继承自Django提供的各种通用视图类。不同的HTTP方法(GET, POST)由类中的不同方法(get(), post())来处理。
我们将实现三个视图:
ArticleListView- 文章列表 (处理GET请求)ArticleDetailView- 文章详情 (处理GET请求)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