记得我刚学Django那会儿,看着教程里的函数视图觉得这玩意儿真简单。一个函数处理一个请求,if request.method == ‘GET’ 就返回数据,if request.method == 'POST' 就保存数据,清晰直白得像一碗蛋炒饭。
直到我的项目变成了“祖传代码”......
那个处理用户管理的views.py文件,已经从最初的50行膨胀到了500行。各种if-else嵌套得像俄罗斯套娃,验证逻辑和业务逻辑纠缠得比耳机线还乱。每次新增功能我都得小心翼翼,生怕碰坏了哪个角落里沉睡的bug。
就在我准备给这个文件办个“500行庆典”的时候,同事老王瞥了一眼我的屏幕,轻飘飘地来了句:“你还在用函数视图啊?类视图它不香吗?”
一、为什么要从函数视图升级到类视图?
1. 告别“if-else地狱”
函数视图处理多个HTTP方法时,通常长这样:
def article_list(request):
if request.method == 'GET':
# 获取文章列表
articles = Article.objects.all()
return JsonResponse({'articles': list(articles.values())})
elif request.method == 'POST':
# 创建新文章
data = json.loads(request.body)
article = Article.objects.create(**data)
return JsonResponse({'id': article.id}, status=201)
else:
return JsonResponse({'error': '方法不允许'}, status=405)
看起来还行?等你要支持PATCH、DELETE、PUT的时候,这个函数就会胖到亲妈都不认识。
而类视图把这些方法拆解成了独立的函数,每个函数专注做一件事:
class ArticleView(View):
def get(self, request):
# 只处理GET请求
pass
def post(self, request):
# 只处理POST请求
pass
这不就是Python界著名的“单一职责原则”吗?
2. 继承的力量,拒绝重复造轮子
假设你有10个API都需要用户登录才能访问。在函数视图里,你要么写10个@login_required装饰器,要么自己写个装饰器。
但在类视图里,你可以:
class LoginRequiredView(View):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return JsonResponse({'error': '请先登录'}, status=401)
return super().dispatch(request, *args, **kwargs)
class ArticleView(LoginRequiredView):
# 这个类自动拥有了登录检查功能!
def get(self, request):
pass
写一次,到处用。这不就是程序员梦寐以求的“偷懒”境界吗?
3. Mixin:像搭积木一样组合功能
Django类视图最强大的地方在于Mixin机制。你可以把各种功能写成独立的Mixin类,然后按需组合:
# 记录操作日志的Mixin
class LoggingMixin:
def dispatch(self, request, *args, **kwargs):
print(f"{request.method}请求到达:{request.path}")
return super().dispatch(request, *args, **kwargs)
# 缓存Mixin
class CacheMixin:
cache_timeout = 60
def get_cache_key(self, request):
return f"view_{request.path}"
class ArticleView(LoggingMixin, CacheMixin, View):
# 这个视图同时拥有了日志和缓存功能!
pass
这种感觉就像吃自助餐,想要什么功能就“夹”什么功能到你的视图里。
二、实战开始:用类视图重写博客API
光说不练假把式,让我们一步步把一个传统的函数视图博客API改造成类视图版本。
改造前:函数视图版博客API
# 旧的views.py
def article_list(request):
if request.method == 'GET':
articles = Article.objects.all()
return JsonResponse({
'articles': list(articles.values('id', 'title', 'created_at'))
})
elif request.method == 'POST':
try:
data = json.loads(request.body)
article = Article.objects.create(
title=data['title'],
content=data['content'],
author=request.user
)
return JsonResponse({'id': article.id}, status=201)
except KeyError:
return JsonResponse({'error': '缺少必要字段'}, status=400)
else:
return JsonResponse({'error': '方法不允许'}, status=405)
def article_detail(request, article_id):
try:
article = Article

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



