CBV和FBV
-
-
CBV(class based view)
1. CBV的定义
# 增加出版社 CBV from django.views import View class AddPublisher(View): def get(self, request): pass def post(self, request): pass
2. CBV使用
url(r'^add_publisher/', views.AddPublisher.as_view()),
3. CBV的流程
views.AddPublisher.as_view() 程序加载的时候执行 ——》 view函数
-
self = AddPublisher()
-
self.request = request
-
执行self.dispatch方法
-
判断请求方式是否被允许
-
允许时,通过反射获取到AddPublisher中定义的get或者post方法 ——》handler
-
不允许时,self.http_method_not_allowed ——》handler
-
-
执行handler 拿到返回结果 Httpresponse对象
CBV的匹配原理:
通过查看View的源码,可以看到里面有很多提交方法
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
使用ajax的时候这些方法都可以使用
这种根据url 来匹配的方法都是通过反射(getattr)获得的. 请求发过来之后,会先走一个dispatch的方法,这个方法在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: handler = getattr(self, request.method.lower(),self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) request.method.lower()
将请求方式变成小写. 通过反射找到类中的对应方法
所有的框架,本质都是通过请求方式, 反射不同的函数
所以CBV的本质,其实还是用的FBV, 只不过用类封装了而已
4. 给CBV加装饰器 method_decorator
from django.utils.decorators import method_decorator
加载到某个get 或者 post的方法上:
@method_decorator(timer) def get(self, request):
加在self.dispatch方法上:
@method_decorator(timer) def dispatch(self, request, *args, **kwargs):
加在类上:
@method_decorator(timer, name='post') @method_decorator(timer, name='get') class AddPublisher(View):
5. 区别
func: <function AddPublisher.dispatch at 0x00000163735176A8>args :<app01.views.AddPublisher object at 0x00000163735F7EF0> <WSGIRequest: GET '/add_publisher/'>
-
使用method_decorator
func:<function method_decorator.<locals>.dec.<locals>.wrapper.<locals>.bound_func at 0x0000019664B4A378>arsgs: <WSGIRequest: GET '/add_publisher/'>
简而言之:
不使用method_decorator的时候, 第二个参数是request
使用method_decorator的时候, 第一个参数是request
print(request.method) # 请求方式 GET 、POST print(request.GET) # get的请求数据 QueryDict{} url携带参数 print(request.POST) # post的请求数据 QueryDict{} form表单提交的post数据 print(request.path_info) # 路径信息 不包含IP和端口、参数
print(request.path) #获取请求路径信息
print(request.body) #获取的是请求体里的数据
print(request.FILES) #上传的文件
上传文件注意事项:
form表单的enctype:multipart/form-data;
method="post";
name="作为键";
{%csrf_token%};
取文件对象的方法: chunks();
request.FILES中获取文件对象
print(request.is_ajax()) #是否是ajax请求 print(request.get_host()) print(request.get_full_path()) # 路径信息 + 参数
response对象
1. HttpResponse("字符串") --->字符串 2. render(request,"模板文件名",{k:v}) ----->完整的页面 3. redirect("要跳转的地址")---> 本质是响应头:Location:url 1. ret=HttpResponse() ret["Location"]=url(设置响应头) 4. JsonResponse({字典}) ContentType:application/json 1.传非字典类型的时候设置: safe=False
文件上传
view.py
# 上传文件 def upload(request): if request.method == 'POST': # print(request.body) file = request.FILES.get('f1') with open(file.name, 'wb') as f: for chunk in file.chunks(): f.write(chunk) return HttpResponse('上传成功') return render(request, 'upload.html') import json from django.http import JsonResponse def json_test(request): data = {'name': 'alex', 'pwd': 'alexdsb'} ret = HttpResponse(json.dumps(data)) ret['Content-Type'] = 'application/json' ret['xxx'] = 'axxx' return ret # return HttpResponse(json.dumps(data), content_type='application/json') # Content-Type: text/html; charset=utf-8 # return JsonResponse(data) # Content-Type: application/json
template
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} 文件:<input type="file" name="f1"> <button>上传</button> </form> </body> </html>
-
form表单的enctype = 'multipart/form-data'
-
request.FILES中获取文件对象
-
使用文件对象的chunks()
from django.http import JsonResponse
def json_test(request):
data = {'name': 'alex', 'pwd': 'alexdsb'}
return JsonResponse(data) # Content-Type: application/json
# return HttpResponse(json.dumps(data), content_type='application/json') # Content-Type: text/html; charset=utf-8