FBV
FBV(function base views) 就是在视图里使用 函数 处理请求。
- 1、仅仅是一个函数,接收request作为参数,return响应的数据;
- 2、返回的数据可以为html页面内容、redirect、404error、image,即任意可以用二进制描述的数据;
- 3、函数内部包含任意逻辑,作用是取出并返回需要的响应数据;
- 4、可以在python解释器能找到的任意路径,但惯例是放在app目录下的
views.py
文件中。
常用的方法
1、
render(request, 'index.html',{k:v,..})
:从数据库中取出数据渲染到模板,再返回给浏览器展示,或者直接返回模板内容到浏览器.2、
HttpResponse(str)
:返回固定字符串,若为标签文本,页面亦可以识别:def index(request): return HttpResponse('<h1>hello django</h1>')
3、
redirect('/login/')
:重新到路由配置下逐条匹配url,再进入对应的视图,返回需要的数据。
CBV模型
CBV(class base views) 就是在视图里使用 类 处理请求。
- url对应一个视图类、此类调用父类的
dispatch()
方法,会根据http请求头里的方法是get
还是post
方法来执行相应的函数。 - 在触发视图类的时候可以在dispatch函数内部实现一些逻辑判断;
CBV源码分析
# step 1:配置路由===================================
url(r'^index/$',views.IndexView.as_view())
# step 2===================================
from django.views import View
class View(object):
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def __init__(self, **kwargs):
pass
@classonlymethod
def as_view(cls, **initkwargs):
# 一般没有传递参数,initkwargs 为 None
for key in initkwargs:
if key in cls.http_method_names:
# 传入的参数不能为方法名称
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# step 3: 调用dispatch方法===================================
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
return view
def dispatch(self, request, *args, **kwargs):
# step 4: 查看请求的方法是否在设定的方法列表中===================
if request.method.lower() in self.http_method_names:
# step 5: 获取方法===================
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# step 6: 调用方法===================
return handler(request, *args, **kwargs)
自定制dispatch函数
from django.views import View
from django.shortcuts import render, redirect,HttpResponse
class LoginView(View):
def dispatch(self, request, *args, **kwargs):
'''可以在内部做出逻辑判断'''
if request.POST.get('username')=='alex':
return HttpResponse('用户名已注册')
ret = super(LoginView, self).dispatch(request, *args, **kwargs)
return ret
def get(self, request):
obj = MyForm()
return render(request, 'login.html', {'form': obj})
def post(self, request):
obj = MyForm(request.POST, request.FILES)
errors = {}
if obj.is_valid():
values = obj.clean()
print(values)
else:
errors = obj.errors
print(errors)
return render(request, 'login.html', {'form': obj, 'errors': errors})
- 弊端:每个视图类内部都需要定义dispatch函数,造成重复代码。
改进:自定制view类,用来继承即可:
from django.views import View from django.shortcuts import render, redirect, HttpResponse from .forms import LoginForm class MyView(View): def dispatch(self, request, *args, **kwargs): """可以在内部做出逻辑判断""" if request.POST.get('username') == 'alex': return HttpResponse('用户名已注册') ret = super(MyView, self).dispatch(request, *args, **kwargs) return ret class LoginView(MyView, View): def get(self, request): obj = LoginForm() return render(request, 'login.html', locals()) def post(self, request): obj = LoginForm(request.POST, request.FILES) errors = {} if obj.is_valid(): values = obj.clean() print(values) else: errors = obj.errors print(errors) return render(request, 'login.html', locals())