目录
Django视图层
编写视图
-
视图函数的执行结果只可能有两种:
1.返回一个包含请求页面元素的
HttpResponse
对象2.或者是抛出
Http404
这类异常。至于执行过程中的其它的动作则由你决定
-
通常来说,一个视图的工作就是:
从参数获取数据,装载一个模板,然后将根据获取的数据对模板进行渲染。
一、视图函数必会三板斧
视图函数必须要有一个返回值,并且这个返回值必须是一个HttpResponse对象
1.HttpResponse()
作用:接收一个字符串并返回
def index_func(request):
url = reverse('app01_view_index')
print(url)
return HttpResponse('app01 的index')
-
源码:
底层是一个类,返回的是一个HttpResponse对象
2.render
作用:返回html页面,并且在返回给浏览器之前还可以给html文件传值
render()
有多个参数,其中第一个参数为返回request
请求对象,其他参数则用于返回HTML
文档及其局部命名空间内变量用作模板渲染。
参数 | 内容 |
---|---|
request | 用于生成响应的请求对象 |
template_name | 要使用的模板的完整名称,可选的参数 |
context | 添加到模板上下文的一个字典 默认是一个空字典 如果字典中的某个值是可调用的,视图将在渲染模板之前调用它 局部命名空间变量(字典形式从换入),或locals()函数 |
def home_func(request):
return render(request, 'HomePage.html')
- 源码
底层也是返回HttpResponse对象
3.redirect
作用:接收一个url
并返回,状态码为302
,也就是重定向
- 源码
redirect_class = 类(祖先有个类是HttpResponse)
二、JsonResponse
- json格式的数据有什么用?
前后端数据交互需要使用到json格式数据作为过渡,实现跨语言传输数据
1.json模块进行序列化
虽然python中为我们准备了json格式的序列化的模块json,但是当我们通过自带的json模块进行序列化展示到浏览器上的时候,
def json_func(request):
data_dict = {'test_content': 'about JsonResponse ', 'age': 22, '爱好': '放空'}
import json
json_data = json.dumps(data_dict, ensure_ascii=False)
return HttpResponse(json_data)
2.JsonResponse
Jsonresponse
是Django
中自带的一个基于json
模块的封装,可以直接返回json
类型的数据至模板层的前端页面
- 浏览器会对这个JsonResponse方法返回的json格式数据更有亲和力,可以当成json字符串渲染
(1)实例
from django.http import JsonResponse
def json_func(request):
data_dict = {'test_content': 'about JsonResponse ', 'age': 22, '爱好': '放空'}
return JsonResponse(data_dict)
(2)JsonResponse源码学习
通过源码的阅读,我们可以发现我们可以通过设置其中参数,改变我们序列化的限制。
safe=False
改变只能序列化字典
def json_func(request):
l1 = [11, 22, ['aaaa'], ('a',)]
return JsonResponse(l1, safe=False)
-
正常显示出中文
json_dumps_params={'ensure_ascii': False}
def json_func(request):
data_dict = {'test_content': 'about JsonResponse ', 'age': 22, '爱好': '放空'}
# l1 = [11, 22, ['aaaa'], ('a',)]
return JsonResponse(data_dict, json_dumps_params={'ensure_ascii': False})
三、request对象获取文件
请注意只有在请求是通过 POST
提交且提交的 <form>
表单有 enctype="multipart/form-data"
属性的时候,[request.FILES
] 才会包含文件数据,否则的话, request.FILES
是空的。
1.前端html页面:form表单上传文件
form表单携带文件类型的数据需要做到以下几点
-
1.
method
必须是post
-
2.
enctype
属性改成multipart/form_data
request.POST只能获取普通数据(输入、选择)
request.FILES用来获取文件数据
获取到的是一个对象,可以点方法
2.后端:request.FILES
获取文件类型的数据
-
如果使用get方法
获取不到文件
None
- request.FILES
def file_func(request):
if request.method == "POST":
print(request.FILES) # <MultiValueDict: {'file': [<InMemoryUploadedFile: ccs.md (application/octet-stream)>]}>
file_obj = request.FILES.get('file') # 拿到文件对象
print(file_obj.name) # ccs.md
with open(file_obj.name, 'wb') as destination:
for chunk in file_obj.chunks(): # # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取
destination.write(chunk)
return render(request, 'testpage.html')
使用
UploadedFile.chunks()
而不是read()
是为了确保即使是大文件又不会将我们系统的内存占满。
四、FBV与CBV
视图函数既可以是函数也可以是类
1.FBV(Function Bases View)
基于函数的视图
def index(request):
return HttpResponse对象
2.CBV(Class Bases View)
基于类的视图,用面向对象的方法写视图类
优点:比FBV灵活,只需要定义与请求方法同名的方法(get和post请求),会自动根据请求方法的不同自动匹配对应的数据,
- Views
from django import views
class MyLoginView(views.View):
def get(self,request)
return HttpReponse('')
def post(self,request)
return HttpReponse('')
- 路由层
path('login/',views.MyLogin.as_view())
(2)CBV源码剖析
1.从CBV的路由匹配切入
path('login/', views.MyLoginView.as_view())
-
1.类名点名字,涉及到名字的查找问题
as_view()
查找类的方法,没有在类中,就应该在类继承的父类中 -
2.类名点名字并加括号调用(静态方法、绑定给类的方法)
as_view被classonlymethod修饰, 相当于classmethod
- 3.函数名加括号 调用优先级最高
# 通过这个闭包函数,相当于
path('login/', views.view)
在这里,可以发现CBV的本质还是FBV
dispatch调度
-
4.浏览器地址访问login路由需要view函数
(1)产生我们编写的类
(2)对象调用dispatch方法
-
5.dispatch方法
获取当前请求方法并转成小写,之后利用反射获取我们编写的类中对应的方法