三板斧介绍
"""
HttpResponse
返回字符类型
render
返回HTML页面,并且可以在返回浏览器之前给HTML文件传值
redirect
重定向
"""
# 视图函数必须要返回一个HttpResponse对象
HttpResponse是一个类
通过查看三板斧的源码可以看到返回的都是HttpResponse或者继承于它
JSONResponse对象
前后端数据交互需要使用json作为过渡,实现跨语言传输数据
def xx_json(request):
# 创建一个字典
user_dic = {'name': '刘苏成是dsb', 'age': '12', 'hobby': 'girl', 'gender': 'boy'}
user_list = ['liu', 111, '刘']
# 导入JSON模块
import json
# 序列化字典,ensure_ascii默认为True,自动把汉字编码成Unicode格式,把参数改为False就会写什么展示什么
dic_json = json.dumps(user_dic, ensure_ascii=False)
# 导入Django中的JsonResponse模块
from django.http import JsonResponse
# 想要写什么展示什么,通过查看JsonResponse的源码得知,添加json_dumps_params={'ensure_ascii': False}即可
dic_json = JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})
# JsonResponse模块默认不能序列化列表,添加safe=False就可以序列化列表了
list_json = JsonResponse(user_list, safe=False, json_dumps_params={'ensure_ascii': False})
return HttpResponse(list_json)
"""
json_dumps_params={'ensure_ascii': False}:添加这个属性可以让JsonResponse模块写什么展示什么,不编码成unicode格式
safe=False:添加这个属性可以让JsonResponse模块能序列化列表,默认是不能序列化列表的
"""
form表单上传文件后,后端获取文件
form表单上传文件记得改两个属性
# form表单要上传文件类型的数据,一定要记得改下面两个属性
1、method="post"
2、enctype="multipart/form-data"
<form action="" enctype="multipart/form-data" method="post"></form>
Django获取文件的方法
request.FILES # 获取用户上传的文件数据
request.FILES.get('file') # 获取一个文件对象
request.FILES.getlist('file') # 获取所有文件对象
request.FILES.get('file').name # 获取文件名
"""
request.POST不能获取到文件数据,需要使用request.FILES来获取文件
想要查看文件中的内容需要使用with文件操作
"""
使用实例
def files(request):
if request.method == 'POST':
# POST方法不能获取到文件对象
quest = request.POST
print(quest)
# request对象方法:获取文件数据
user_files = request.FILES
# 获取文件对象
files_obj = user_files.get('file')
# 文件对象方法:获取文件名
files_name = files_obj.name
# 要查看获取的文件对象的内容,要使用with
with open(files_obj.name, 'wb') as f:
for info in files_obj.chunks(): # django推荐加上chunks方法,虽然加不加都是一样,都是一行行的读
f.write(info)
print(user_files)
print(files_obj)
print(files_name)
return render(request, 'files.html')
request对象方法
request.method # 返回大写的请求方法:POST/GET
request.POST # 获取post请求
request.GET # 获取get请求
request.FILES # 获取文件
"""path与path_info是差不多的,记住一个就可以了"""
request.path # 获取用户输入的路由:/app01/file/
request.path_info # 获取用户输入的路由:/app01/file/
request.path_full_path() # 获取用户输入的路由及问号后面的参数:/app01/file/?username=liu
request.body # 原生的浏览器发过来的二进制数据,现在暂时了解,详细在后面
FBV与CBV简介
视图函数中可以是函数也可以是类
FBV就是函数
FBV使用
"""路由层"""
url(r'^login/', views.login)
"""视图层"""
def login(request):
return render(request, 'login.html')
CBV就是类
CBV简单使用
"""路由层"""
url(r'^cbv/', views.MyCBV.as_view())
"""视图层"""
# 需要导入View模块
from django.views import View
# 特点:能够直接根据请求方式的不同直接匹配到对应的方法执行
# 需要继承View父类
class MyCBV(View):
# 当请求为get请求时运行该函数
def get(self, request):
return render(request, 'files.html')
# 当请求为post请求时运行该函数
def post(self, request):
return HttpResponse('这是post请求')
CBV源码剖析
1、解析路由层中的as_view是什么
1、解析路由层中的as_view是什么
"""
函数名/方法名 加括号执行优先级最高
猜测as_view()要么是被@staicmethod修饰的静态方法,
要么是被classmethod修饰的类方法
下面来查看源码
"""
# 通过查看as_view的源码得知,是被classmethod修饰的类方法(classmethod与classonlymethod差不多一个意思)
@classonlymethod
def as_view(cls, **initkwargs):
pass
2、解析as_view返回了什么
2、解析as_view返回了什么
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
pass
return view
"""
查看as_view部分源码得知,这是一个闭包函数
最后的返回值是view
也就是当用户输入的地址匹配上的时候就会立刻执行as_view方法中的view方法
"""
# 所以路由层中的 url(r'^login/', views.MyCBV.as_view()), 可以变形为
url(r'^login/', views.view), # 与FBV一模一样
"""所以CBV与FBV在路由匹配上本质是一样的,都是路由 对应 函数内存地址"""
3、查看view方法中写了什么
3、查看view方法中写了什么
# as_view方法中的view方法
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls是我自己写的类(视图函数中定义的类)
# self = MyCBV(**initkwargs) 产生一个我们自己写的类的对象
# 暂时不用看
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# 给我们定义的类的对象赋值属性,也可以暂时不用管
self.request = request
self.args = args
self.kwargs = kwargs
"""
在看Python源码的时候一定要时刻提醒自己面向对象属性方法查找顺序
先从对象自己找
再从产生对象的类里面找
最后再去父类找
...
总结:看源码只要看到了self点一个东西,一定要问自己当前这个self到底是谁
"""
# 通过上述规律,dispatch方法在父类View中找到
return self.dispatch(request, *args, **kwargs)
4、查看dispatch方法中写了什么
4、查看dispatch方法中写了什么
# dispatch是整个CBV的精髓所在
def dispatch(self, request, *args, **kwargs):
# 以get请求为例
# 获取当前请求的小写格式(lower方法转换大写为小写),然后判断当前请求是否合法
if request.method.lower() in self.http_method_names:
"""
getattr:反射
通过字符串来操作对象的属性或者方法
"""
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# handler = getattr(自己写的类的对象,'get', 当找不到get属性或者方法的时候就会用到第三个参数)
# handler = 我们自己写的类里面的get方法
else:
# 请求不合法会报错
handler = self.http_method_not_allowed
# 最后自动调用我们类里面写的get方法
return handler(request, *args, **kwargs)
"""
这就是为什么CBV可以根据不同的请求来做不同的操作的关键
getattr(self, request.method.lower(), self.http_method_not_allowed)
"""
5、总结:CBV内部执行流程
url(r'^login/', views.MyCBV.as_view())
"""
MyCBV是我们自己写的类,里面有get和post两个方法,分别对应get和post请求
用户输入loign,调用as_view方法,把MyCBV类传进去
as_view是一个闭包函数,返回view方法,就相当于 url(r'^login/', views.view)
view方法把我们写的类产生一个对象,然后点dispatch方法,进入CBV的精髓所在
dispatch先判断请求是否合法,合法后通过反射:getattr方法,看我们写的类中是否有get或者其他合法请求的方法
我们的类中有get或者其他合法请求的方法,dispatch自动帮我们调用该方法,所以CBV才能根据不同的请求来做相应的操作
"""
标签:files,get,self,request,视图,方法,第四章,view
From: https://www.cnblogs.com/liuhousheng/p/17044730.html