三、Django之视图层
Django之视图层
1、三板斧
"""
HttpResponse
返回字符串类型
render
返回html页面,并且在返回给浏览器之前还可以给html文件传值
redirect
重定向
如果我们一个视图函数没有返回值的话,会直接报如下错误
The view app01.views.index didn't return an HttpResponse object. It returned None instead.
点击三板斧的源码,我们会发现最后都是HttpResponse对象,所以视图函数必须要返回HTTPResponse对象
"""
# render简单内部原理
from django.template import Template,Context
res = Template('<h1>{{ user }}</h1>')
con = Context({ 'user':{'username':'jason','password':123} })
ret = res.render(con)
return HttpResponse(ret)
2、JsonResponse对象
"""
json格式的数据可以跨语言交互,前端后端数据加护需要使用使用json作为过渡
前端序列化 后端序列化(python)
JSON.stringify() json.dumps()
JSON.parse() json.loads()
"""
-
原始方法实现数据序列化
# 在视图函数中,我们要把一个字符串的数据转化成json数据,然后传递给前端 import json from django.http import JsonResponse def ab_json(request): user_dict = {'username':'jason','password':123,'hobby':'read'} # json模块方式,ensure_ascii=False在dumps里默认是True,默认不显示中文字符 json_str = json.dumps(user_dict,ensure_ascii=False) return HttpResponse(json_str)
-
使用JsonResponse实现数据序列化
import json from django.http import JsonResponse def ab_json(request): user_dict={'username':'jason','password':123,'hobby':'read'} return JsonResponse(user_dict,json_dumps_parse={'ensure_ascii':False}) # 读源码可以知道 本质上还是用json模块实现的,只是添加了一些其他的功能
-
注意:JsonResponse默认只能序列化字典,序列化其他需要加safe参数
# 默认只能序列化字典,序列化其他需要加safe参数 import json from django.http import JsonResponse def ab_json(request): l = [111,222,333,444,555] return JsonResponse(l,safe=False)
3、from表单上传文件及后端获取
-
注意:from表单上传文件类型的数据
- method必须指定成post
- enctype必须换成multipart/form-data
-
具体实现
def ab_fire(request): if request.method == 'POST': # print(request.POST) 只能获取普通的简单键值对 文件不行 print(request.FIRE) # 获取列表嵌对象的文件数据对象 # <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}> fire_obj = request.FIRE.get('fire') # 获取具体的文件对象 with open(fire_obj.name,'wb') as f: for line in fire_obj.chunks(): # 官方推荐加上chunks方法 其他加不加都一样 f.write(line) return render(request,'from.html')
4、FBV与CBV
-
FBV(function base views)
# 路由层 url(r'^login/',views.login) # 视图层 def login(request): user_id = request.GET.get('user_id') user_obj = models.User.object.filter(id=user_id).first() if request.method == 'POST': user_name = request.POST.get('username') pass_word = request.POST.get('password') if user_obj: if user_obj.password == pass_word: return HttpResponse('登录成功') else: return HttpResponse('登录失败') return redirect('/register/')
-
CBV(class base views)
# 路由层 url(r'^login/',views.Login.as_view()) # 视图层 from django.views import View class Login(View): def get(self,request): return render(request,'form.html') def post(self,request): return HttpResponse('post方法') # CBV可以根据不同的请求直接匹配到不同的方法去执行
5、CBV源码
# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())
"""
函数名/方法名加括号执行优先级最高
猜测
as_view()
要么是被staticmethod修饰的静态方法
要么是被classmethod修饰的类方法 ------ 正确
@classonlymethod
def as_view(cls,**initkwargs):
pass
"""
# 具体源码解析
# 1.as_view里面的源码
@classonlymethod
def as_view(cls,**initkwargs):
# cls就是我们自己写的类 MyLogin
def view(request,*args,**kwargs):
self = cls(**initkwargs) # cls就是我们自己写的类
# self = MyLogin(**initkwargs) 产生一个我们自己写的类的对象
return self.dispatch(request,*args,**kwargs)
"""
以后我们会经常需要看源码 但是在看python源码的时候 一定要时刻提醒自己面向对象属性方法查询顺序
先从对象自己这里找
再去产生对象的类里面找
之后再去父类里面找
...
总结:看源码只要看到了self点一个东西 一定要问你自己当前这个self到底是谁
"""
view.view_class = cls
view.view_initkwargs = initkwargs
update_wrapper(view, cls, updated=())
update_wrapper(view, cls.dispatch, assigned=())
return view
# 2.dspatch里的源码 CBV的精髓
def dispatch(self,request,*args,**kwargs):
# 获取当前请求的小写格式,然后对比当前请求方式是否合法
# get请求为例
# post请求为例
if request.method.lower() in self.http_method_names:
handler = getattr(self,request.method.lower(),self.http_method_not__allowed)
"""
反射:通过字符串来操作对象的属性或者类方法
handler = getattr(自己写的类产生的对象,'get',当前找不到get属性或者方法的时候就会使用第三个参数)
handler = 我们自己写的类里面的get方法
"""
else:
handler = self.http_method_not_allowed
return handler(request,*args,**kwargs)
"""自动调用get方法"""