django04--视图层
1 响应对象
1.1 响应对象之三板斧
from django.shortcuts import render, HttpResponse, redirect
# 1.HttpResponse对象:返回字符串类型
return HttpResponse("收到了 宝贝")
# 2.render对象:返回html页面
并且在返回给浏览器之前还可以给html文件传值
return render(request, 'login.html')
# 3.redirect对象:重定向
return redirect('/home/')
# 注:
三者的实质:都是HttpResponse对象
# 视图函数必须要返回一个HttpResponse对象 正确 研究三者的源码即可得处结论
The view app01.views.index didn't return an HttpResponse object. It returned None instead.
# render简单内部原理
from django.template import Template,Context
res = Template('<h1>{{ user }}</h1>')
con = Context({'user':{'username':'jason','password':123}})
ret = res.render(con)
print(ret)
return HttpResponse(ret)
1.2 响应对象之JsonResponse
# json格式的数据有什么用?
前后端数据交互需要使用到json作为过渡 实现跨语言传输数据
# js序列化
JSON.stringify() json.dumps()
JSON.parse() json.loads()
# JsonResponse对象
JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应
# 注:
1.关闭 自动转ASCII码
JsonResponse(dict_obj, json_dumps_params={'ensure_ascii':False})
2.默认只能序列化字典 其他类型需要加safe参数
return JsonResponse(list_obj, safe=False)
# eg:返回json格式字符串给前端
import json
from django.http import JsonResponse
def ab_json(request):
user_dict = {'username':'jason好帅哦,我好喜欢!','password':'123','hobby':'girl'}
l = [111,222,333,444,555]
# 方式一: 利用json模块
# 先转成json格式字符串
json_str = json.dumps(user_dict,ensure_ascii=False) # 需要将参数 自动转ASCII码 关掉
# 将该字符串返回
return HttpResponse(json_str)
# 方式二:利用JsonResponse 读源码(源码也是利用json模块)掌握用法*****
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
# 列表转json
# 报错信息:In order to allow non-dict objects to be serialized set the safe parameter to False.
# 默认只能序列化字典 序列化其他需要加safe参数
return JsonResponse(l, safe=False)
1.3 form表单上传文件及后端处理
# 前端form表单 上传 文件类型的数据
1.method必须指定成post
2.enctype必须换成formdata
# 后端获取:
普通的键值对 :request.POST
文件 :request.FILES
# 前端: 可以传文件和数据一起传
<input type="file" name="file"> # 只能获取一个
<input type="file" name="file" multiple> # 可以一次性获取多个
<body>
<form action="" method="post" enctype="multipart/form-data">
<p>username:
<input type="text" name="username">
</p>
<p>
file:
<input type="file" name="file">
</p>
<input type="submit" value="提交">
</form>
</body>
# 后端:
def ab_file(request):
if request.method == 'POST':
# print(request.POST) # 只能获取普通的键值对数据 文件不行
print(request.FILES) # 获取文件数据
# <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}>
file_obj = request.FILES.get('file') # 文件对象
print(file_obj.name) # 获取文件对象的名字
# 保存文件对象
with open(file_obj.name,'wb') as f:
for line in file_obj.chunks(): # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取
f.write(line)
return render(request,'form.html')
2 请求对象
request.method # 返回请求方式 并且是全大写的字符串形式
request.POST # 获取用户post请求提交的普通数据 不包含文件
request.POST.get() # 只获取列表最后一个元素
request.POST.getlist() # 直接将列表取出
request.GET # 获取用户提交的get请求数据 请求url问号后面的数据
request.GET.get() # 只获取列表最后一个元素
request.GET.getlist() # 直接将列表取出
# 注:
get请求携带的数据是有大小限制的 大概好像只有2KB左右,而post请求则没有限制
request.FILES # 获取文件对象字典 类似字典形式,包含多个文件对象
request.FILES.get('file') # 获取'file'文件对象
request.body # 原生的浏览器发过来的二进制数据 后面详细的讲
request.path
request.path_info # 只能获取url,不能获取到后面携带的参数
request.get_full_path() # 能过获取完整的url及问号后面的参数
# eg:
print(request.path) # /app01/ab_file/
print(request.path_info) # /app01/ab_file/
print(request.get_full_path()) # /app01/ab_file/?username=jason
3 视图函数
一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应。
3.1 FBV与CBV
# 视图函数既可以是函数也可以是类
FBV(function base views) 使用函数 处理请求
CBV(class base views) 使用类 处理请求
# FBV 基于函数的视图
def index(request):
return HttpResponse('index')
# CBV 基于类的视图
CBV能够直接根据请求方式的不同,直接匹配到对应的方法执行
# CBV路由
url(r'^login/',views.MyLogin.as_view())
# CBV视图
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'form.html')
def post(self,request):
return HttpResponse('post方法')
3.2 CBV源码剖析
利用 反射:通过字符串来操作对象的属性或者方法
# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())
url(r'^login/',views.view) # 与FBV一模一样
# CBV与FBV在路由匹配上本质是一样的 都是路由 对应 函数内存地址
"""
函数名/方法名 加括号执行优先级最高
猜测
as_view()
要么是被@staicmethod修饰的静态方法
要么是被@classmethod修饰的类方法 正确
@classonlymethod
def as_view(cls, **initkwargs):
pass
"""
from django.views import View
class View:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
@classonlymethod
def as_view(cls, **initkwargs):
"""
cls就是我们自己写的类 MyCBV
Main entry point for a request-response process.
"""
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls是我们自己写的类
# self = MyLogin(**initkwargs) 产生一个我们自己写的类的对象
return self.dispatch(request, *args, **kwargs)
"""
以后你们会经常需要看源码 但是在看python源码的时候 一定要时刻提醒自己面向对象属性方法查找顺序
先从对象自己找
再去产生对象的类里面找
之后再去父类找
...
总结:看源码只要看到了self点一个东西 一定要问你自己当前这个self到底是谁
"""
return view
# CBV的精髓 getattr反射机制
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方法
"""
# 要求掌握到不看源码也能够描述出CBV的内部执行流程(******)