django学习第二天---django视图系统,基于类的视图写法,FBV和CBV加装饰器
django视图系统
request对象
- 常用属性和方法
print(request) #wsgirequest对象
print(request.path) #请求路径 /index/
print(request.method) #请求方法 POST GET
print(request.POST) #post请求提交的数据<QueryDict:{'username':['root']}>
print(request.GET) #获取url中的查询参数 路径后面?a=1&b=1 返回 <QueryDict:{'a':['1'],'b':['2']}> 不是针对get请求的
print(request.body) #获取http请求消息格式的请求数据部分的内容 bytes类型 b''
print(request.META) #请求头信息
print(request.get_full_path()) #获取完整路径(包含查询参数) /index/?a=1
print(request.FILES) #上传的文件对象数据
print(request.FILES.get('file')) #返回文件对象 获取文件名可以用文件对象.name
#注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
包含数据。否则,FILES 将为一个空的类似于字典的对象。
print(request.POST.get('username')) #获取键对应的值
print(request.GET.get('sex')) # 获取键对应的值
#多选提交来的数据通过getlist来获取
print(request.POST.getlist('hobby')) #['2','3']
response响应
常用方法
from django.shortcuts import render,HttpResponse,redirect
return HttpResponse('你好') #回复字符串
return render(request,'home.html') #回复html页面
#重定向方法,参数是个路径
return redirect('/home/') #封装了302状态码,以及浏览器要重定向的路径
添加响应头键值对
ret = render(request,'home.html')
ret['a'] = 'b' #添加响应头键值对
return ret
添加响应状态码
ret = render(request,'home.html',status=202)#render修改状态码还可以这样改
ret.status_code = 201 #添加响应状态码
return ret #回复html页面
CBV和FBV
- 两种视图逻辑的写法方法
FBV:全称function based view,就是基于函数来写视图逻辑
CBV:全称class based view,就是基于类来写视图
- 基于函数的写法
urls.py写法
url(r'^index/(\d+)',views.index)
views.py写法
def index(request,xx):
if request.method == 'get':
return render(request,'index.html')
elif rquest.method == 'post':
return HttpResponse('你好')
- 基于类的视图写法
urls.py文件写法
#类视图的url
url(r'^login/',views.LoginView.as_view())
views.py文件写法
#需要导入View这个类,然后继承View这个类
from django.views import View
#登录需求
class LoginView(View): #继承这个View父类
#get请求 获取login页面
def get(self,request):
return render(request,'login.html')
#post请求,获取post请求提交的数据,并校验等
def post(self,request):
print(request.POST)
#<QueryDict:{'uname',['wei'],'pwd':['123']}>
return render(request,'login.html')
CBV源码重点(反射)
from django.views import View
View里面的dispatch方法中的反射逻辑,实现了不同的请求方法,找到我们视图类中的对应方法执行
#源码如下:
@classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.
"""
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__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
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
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
#http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return http.HttpResponseNotAllowed(self._allowed_methods())
FBV和CBV加装饰器
- FBV和普通函数加装饰方式一样
#装饰器函数
def outer(f):
def inner(request,*args,**kwargs):
print('执行之前做的事')
ret = f(request,*args,**kwargs)
print('执行之后做的事')
return ret
return inner
#使用装饰器
@outer
def books(request):
print('FBV执行了')
return HttpResponse('OK')
- CBV加装饰器
from django.utils.decorators import method_decorator #加装饰器需要导入这个类
from django.views import View #类视图需要导入这个View类,并继承这个父类
#装饰器函数
def outer(f):
def inner(request,*args,**kwargs):
print('执行之前')
ret = f(request,*args,**kwargs)
print('执行之后')
return ret
return inner
# 方法一 在每个方法上加装饰器
class LoginView(View):
@method_decorator(outer)
def get(self,request):
print('get方法')
return render(request,'home.html')
@method_decorator(outer)
def post(self,request):
print('post方法')
return HttpResponse('ok')
方法二:统一加一个装饰器
class LoginView(View):
# 给类方法统一加装饰器,借助dispatch方法(父类的dispatch方法,
# 就是通过反射来完成不同的请求方法找到并执行我们自己定义的视图类的对应方法)
@method_decorator(outer)
def dispatch(self, request, *args, **kwargs):
print('调用方法之前')
ret = super().dispatch(request,*args,**kwargs) #重写父类的方法 返回的结果就是调用下面的get 或 post方法
print('调用方法之后')
return ret
def get(self,request):
print('get方法执行啦')
return render(request,'home.html')
def post(self,request):
print('post方法执行啦')
return HttpResponse('ok')
执行顺序:get方法和post方法
执行之前
调用方法之前
get方法执行啦
调用方法之后
执行之后
#方法三 在类上面加装饰器
@method_decorator(outer,name='post')
@method_decorator(outer,name='get')
class LoginView(View):
def get(self,request):
print('get方法来啦')
return render(request,'home.html')
def post(self,request):
print('post方法来啦')
return HttpResponse('ok')
-------------------------------------------
个性签名:代码过万,键盘敲烂!!!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!