基于函数的视图实现方式FBV
不能像CBV
一样继承Django的基础视图类
FBV
的建议
➤ Less view code is better.Keep your views simple.
精简代码
➤ Never repeat code in views.
DRY不要重复代码
➤ Views should handle presentation logic. Try to keep business logic in models when possible,
or in forms if you must.
处理一些展示的逻辑, 业务逻辑最好放在model中或者是form中
➤ Use them to write custom 403, 404, and 500 error handlers.
处理错误
➤ Complex nested-if blocks are to be avoided.
尽量不要出现复杂的,嵌套的 if-else 代码块
传递Django中的 django.http.HttpRequest object
或者 django.http.HttpResponse object
除了使用中间件 middleware
上下文 context processors
, 可以创建一些公用的方法对
django.http.HttpRequest object
进行处理
# sprinkles/utils.py
# 1
from django.core.exceptions import PermissionDenied
def check_sprinkle_rights(request):
if request.user.can_sprinkle or request.user.is_staff:
return request
# Return a HTTP 403 back to the user
raise PermissionDenied
# 2
from django.core.exceptions import PermissionDenied
def check_sprinkles(request):
if request.user.can_sprinkle or request.user.is_staff:
# By adding this value here it means our display templates
# can be more generic. We don't need to have
# { if request.user.can_sprinkle or request.user.is_staff }
# instead just using
# { if request.can_sprinkle }
request.can_sprinkle = True
return request
# Return a HTTP 403 back to the user
raise PermissionDenied
在视图中使用 FBV
# sprinkles/views.py
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from .models import Sprinkle
from .utils import check_sprinkles
def sprinkle_list(request):
"""Standard list view"""
request = check_sprinkles(request)
return render(request,
"sprinkles/sprinkle_list.html",
{"sprinkles": Sprinkle.objects.all()}
)
def sprinkle_detail(request, pk):
"""Standard detail view"""
request = check_sprinkles(request)
sprinkle = get_object_or_404(Sprinkle, pk=pk)
return render(request, "sprinkles/sprinkle_detail.html",
{"sprinkle": sprinkle})
def sprinkle_preview(request):
"""Preview of new sprinkle, but without the
check_sprinkles function being used.
"""
sprinkle = Sprinkle.objects.all()
return render(request,
"sprinkles/sprinkle_preview.html",
{"sprinkle": sprinkle})
在视图中使用 CBV
from django.views.generic import DetailView
from .models import Sprinkle
from .utils import check_sprinkles
class SprinkleDetail(DetailView):
"""Standard detail view"""
model = Sprinkle
def dispatch(self, request, *args, **kwargs):
request = check_sprinkles(request)
return super(SprinkleDetail, self).dispatch(
request, *args, **kwargs)
对 FBV
视图函数使用 装饰器
import functools
def decorator(view_func):
@functools.wraps(view_func)
def new_view_func(request, *args, **kwargs):
# You can modify the request (HttpRequest) object here.
response = view_func(request, *args, **kwargs)
# You can modify the response (HttpResponse) object here.
return response
return new_view_func
使用装饰器改写上面的例子
# sprinkles/decorators.py
from functools import wraps
from . import utils
# based off the decorator template from the previous chapter
def check_sprinkles(view_func):
"""Check if a user can add sprinkles"""
@wraps(view_func)
def new_view_func(request, *args, **kwargs):
# Act on the request object with utils.can_sprinkle()
request = utils.can_sprinkle(request)
# Call the view function
response = view_func(request, *args, **kwargs)
# Return the HttpResponse object
return response
return new_view_func
# sprinkles/views.py
from django.shortcuts import get_object_or_404, render
from .decorators import check_sprinkles
from .models import Sprinkle
# Attach the decorator to the view
@check_sprinkles
def sprinkle_detail(request, pk):
"""Standard detail view"""
sprinkle = get_object_or_404(Sprinkle, pk=pk)
return render(request, "sprinkles/sprinkle_detail.html",
{"sprinkle": sprinkle})
functools.wraps()
是python的标准包中的方法, 可以保持被装饰函数的原始数据
metadata including critical data like docstring