Django-视图层
目录
-三板斧
HttpResponse,render,redirect
注:三板斧用在视图函数都返回得HttpResponse对象,三者均符合(看源码)
-JsonResponse对象
前后端数据交互需要使用到json作为过渡 实现跨语言传输数据
--使用推导
import json def to_json(request): user_dict = {'name': 'weer好帅', 'password': 666, 'hobby': 'python'} user_dict_json = json.dumps(user_dict) return HttpResponse(user_dict_json) 但若数据出现汉字,则在前端会出现自动转Unicode码情况 {"name": "weer\u597d\u5e05", "password": 666, "hobby": "python"} 此时点dumps看源码,发现其中有个参数ensure_ascii=True默认为True,即数据在前端展示时会自动转储为Unicode码,所以: import json def to_json(request): user_dict = {'name': 'weer好帅', 'password': 666, 'hobby': 'python'} user_dict_json = json.dumps(user_dict, ensure_ascii = False) return HttpResponse(user_dict_json) 此时就可实现不自动转码的情况了 {"name": "weer好帅", "password": 666, "hobby": "python"}
--使用
但其实Django提供了一个JsonResponse对象,用来完成上述操作
from django.http import JsonResponse def to_json(request): user_dict = {'name': 'weer好帅', 'password': 666, 'hobby': 'python'} return JsonResponse(user_dict)
但还是会出现转Unicode码的情况,查看JsonResponse源码,发现其中的json_dumps_params参数有个if判断,若为空,则返回空字典。
所以我们可以自己加上一个该参数传入一个字典,就不会进入if判断里了,且若传入ensure_ascii参数还能实现不转码:
def to_json(request): user_dict = {'name': 'weer好帅', 'password': 666, 'hobby': 'python'} return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})
那其它数据类型能不能被JsonResponse序列化呢?比如列表
def to_json(request): # 列表序列化 l = [111, 222, 333, 444, 555] return JsonResponse(l) # 启动Django项目输入路径,报错:In order to allow non-dict objects to be serialized set the safe parameter to False. 说为了让非字典能被序列化我们需要设置一个safe参数让其为False。 # 所以: def to_json(request): l = [111, 222, 333, 444, 555] return JsonResponse(l, safe=False)
此时就可以了
-文件上传
request.POST只能获得普通键值对数据,不能获取文件数据
所以用request.FILES来获取文件数据
def get_file(request): if request.method == 'POST': # print(request.POST) # 只能拿到普通数据 print(request.FILES) # <MultiValueDict: {'file': [<InMemoryUploadedFile: 雪儿.jpg (image/jpeg)>]}> file_obj = request.FILES.get('file') file_name = file_obj.name print(file_name) # 输出文件名:雪儿.jpg # 保存上传文件 with open(file_name, 'wb') as f: for line in file_obj.chunks(): #.chunks()可不写,但官方推荐加上 f.write(line) return render(request, 'html08 form_get_file.html')
-request对象方法补充
request.method request.POST request.GET request.FILES request.path <==> request.path_info # 获取用户输入路径url /getfile/ request.get_full_path() # 获取完整url及?后参数后缀 /getfile/?name=%27weer%27 request.body # 获取浏览器发过来的原生二进制数据
-FBV与CBV
--FBV
FBV(基于函数的视图),就是在url中一个路径对应一个函数
urls.py path('test/', views.test) views.py def test(requset): return HttpResponse('test')
--CBV
CBV(基于类的视图),就是在url中一个路径对应一个类,在类中写视图函数
# CBV urls.py path('login/', views.LoginView.as_view()) views.py from django.views import View class LoginView(View): # 写视图函数 def get(self, request, *args, **kwargs): return HttpResponse('get请求') def post(self, request, *args, **kwargs): return HttpResponse('post请求')
CBV执行源码剖析:
path('seecbv/', views.MyViews.as_view())中的as_view()点进去看, 该方法中闭包了一个view方法,自动return view方法, 所以我们写的路径等价于还是FBV方法path('seecbv/', views.vies); 再看view方法,其中self是我们自己创建的类,返回的是该self.dispatch()方法, 再看dispatch方法,会首先判断request.method是否是在http请求中的一种, 若在,然后利用类的反射getattr()通过字符串得到该所对应的函数或方法, 用handler来接收,最终结果即return handler(…)来处理, 即可CBV自动调用我们写的get or post方法了。