Django 视图请求对象与相应对象,forms文件上传
一、视图函数
视图层介绍
一个视图函数
,简称视图
,是一个简单的 Python 函数,它接受 Web 请求并且返回 Web 响应。
响应可以是一个 HTML 页面、一个 404 错误页面、重定向页面、XML 文档、或者一张图片...
每个视图函数都负责返回一个 HttpResponse
对象,对象中包含生成的响应。
代码写在哪里都可以,只要在 Python 目录下面,一般约定是将视图放置在项目或应用程序目录中的名为views.py
的文件中。
视图层作用
- 作用:主要存放业务核心逻辑代码
视图层,熟练掌握两个对象即可:请求对象(request)和响应对象(HttpResponse)
二、请求对象HttpRequest 对象(简称 request 对象)
request.method
- 获取当前请求的请求方式并且结果是一个纯大写的字符串类型
实例:
def runoob(request):
name = request.method
print(name)
return HttpResponse('点我有惊喜')
request.GET
-
可以看成一个字典
-
有相同的键,就把所有的值放到对应的列表里。
-
取值格式:对象.方法。
-
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
-
getlist():获取整个列表
示例:
def test(request):
# name = request.GET.get('name')
name = request.GET.getlist('name')
return HttpResponse(f'{name}')
request.POST
-
可以直接看成字典
-
取值格式: 对象.方法。
-
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
-
getlist():获取整个列表
def test(request):
# name = request.POST.get('name')
name = request.POST.getlist('name')
return HttpResponse(f'{name}')
request.FILES
- 可以直接看成字典
- 获取用户上传文件数据
- get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
- getlist():获取整个列表
def test(request):
# name = request.FILES.get('name')
name = request.FILES.getlist('name')
return HttpResponse(f'{name}')
三、响应对象与三板斧本质
响应对象
- 响应对象主要有三种形式:httpResponse、render、redirect
httpResponse()
HttpResponse():
返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。
示例:
def httpresponse(request):
# return HttpResponse('点我有惊喜')
return HttpResponse("<a href='http://www.baidu.com/'>点我有惊喜<a>")
render()
- render(): 返回文本,第一个参数为 request,第二个参数为字符串(页面名称),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)。
示例:
def red(request):
name = '点我有惊喜'
return render(request, 'login.html', {'name': name})
rediect()
- redirect():重定向,跳转新页面。参数为字符串,字符串中填写页面路径。一般用于 form 表单提交后,跳转到新页面。
示例:
def runoob(request):
return redirect("/index/")
三板斧本质与源码分析
Httpresponse源码
- django视图函数必须要返回一个HttpResponse对象
- 否则报错:
The view app01.views.func1 didn't return an HttpResponse object. It returned None instead.
提示你没有返回一个Httpresponse对象而是返回了一个None。
为什么必须要返回这个对象呢?我们 Ctrl + 鼠标点击分别查看三者的源码来查探究竟。
class HttpResponse(HttpResponseBase):
"""
An HTTP response class with a string as content.
This content that can be read, appended to or replaced.
"""
streaming = False
def __init__(self, content=b'', *args, **kwargs):
super(HttpResponse, self).__init__(*args, **kwargs)
# Content is a bytestring. See the `content` property methods.
self.content = content
由此可得,HttpResponse()就是对象,括号内直接跟一个具体的字符串作为响应体,示例如下
HttpResponse(): 返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。
def runoob(request):
# return HttpResponse("小欣博客")
return HttpResponse("小欣博客")
render源码
- 底层返回的也是 HttpResponse 对象
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
'''
render(request, template_name[, context])` `结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
request: 用于生成响应的请求对象。
template_name:要使用的模板的完整名称,可选的参数
context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
'''
redirect源码
- redirect内部是继承了HttpRespone类
小结:
响应对象
- 响应对象主要有三种形式:HttpResponse(),render(),redirect()
- HttpResponse():返回文本,参数为字符串,字符串中写文本内容。
- render():返回文本,第一个参数为request,第二个参数为 字符串(或html页面文件),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)
- redirect():重定向,跳转到新页面。参数为字符串,字符串中填写页面路径。一般用于form提交数据后跳转到新页面
三板斧本质:
ender 和 redirect 是在 HttpResponse 的基础上进行了封装:
- render:底层返回的也是 HttpResponse 对象
- redirect:底层继承的是 HttpResponse 对象
四、JsonResponse
1.作用
全称:JSON的全称是"JavaScript Object Notation", 意思是JavaScript对象表示法
作用:前后端交互一般使用的是json实现数据的跨域传输。
2.向前端返回一个json格式字符串的两种方式
2.1 直接自己序列化
import json
def func2(request):
d = {'user': 'shawn', 'password': 1313, 'sex': '男', 'hobby': '吃泔水'}
res = json.dumps(d, ensure_ascii=False)
return HttpResponse(res)
添加
ensure_ascii=False
参数是为了让中文保持正常显示, 不然会转换成uncode格式
2.2 使用JsonResponse对象
def func2(request):
user_info = {'user': 'shawn', 'password': 1313, 'sex': '男', 'hobby': '吃泔水'}
return JsonResponse(user_info)
问题:JsonResponse 对象没有 ensure_ascii
参数来保证中文正常显示吗?
首先,我们来查看源码。
由源码可知,json_dumps_params
是一个字典,接下来我们为json_dumps_params
传入参数。
from django.http import JsonResponse
def func2(request):
user_info = {'user': 'shawn', 'password': 1313, 'sex': '男', 'hobby': '吃泔水'}
return JsonResponse(user_info,json_dumps_params={'ensure_ascii':False})
需求:给前端返回json格式数据
方式1:自己序列化
res = json.dumps(d,ensure_ascii=False)
return HttpResponse(res)
方式2:JsonResponse
from django.http import JsonResponse
def func2(request):
d = {'user':'jason好帅','password':123}
return JsonResponse(d)
ps:额外参数补充
json_dumps_params={'ensure_ascii':False} # 看源码
safe=False # 看报错信息
效果如下:
再来思考,如果是一个列表呢?怎么去序列化?
def func2(request):
ll=[1,2,3,4,5]
return JsonResponse(ll,json_dumps_params={'ensure_ascii':False})
前端运行报错:TypeError at /app01/func2,In order to allow non-dict objects to be serialized set the safe parameter to False.
提示为了让非字典对象能够被序列化,设置safe参数为false。
我代码没有写这个啊,这是哪来的呢?
凭空捏造??且看JsonResonse
源代码
加入 safe=False
参数, 让其允许非 dict 对象被序列化
def func2(request):
ll = [1, 2, 3, 4, 5]
return JsonResponse(ll, safe=False, json_dumps_params={'ensure_ascii': False})
ps:JsonResponse
返回的也是HttpResponse
对象
class JsonResponse(HttpResponse): # 继承了HttpResponse
...
综上所述,其实这是一种解决遇到报错或查看源码的思路。
你学废了吗?
五、上传文件
1.form表单上传文件注意事项
method
必须是post
enctype
参数修改为multipart/form-data
2.实现代码
test.html文件
<body>
<div class="container">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post" enctype="multipart/form-data">
<input type="file" class="form-control" name="myfile">
<input type="submit" class="btn btn-warning btn-block" value="提交">
</form>
</div>
</div>
</body>
views.py文件
def form_test(request):
if request.method == "POST":
# 从文件对象字典中获取名为"myfile"的文件对象
file_obj = request.FILES.get('myfile')
file_name = file_obj.name
# 保存方式一:
with open(f'./{file_name}',"wb")as f:
for line in file_obj:
f.write(line)
# 保存方式二:(官方推荐)
with open(f'./{file_name}',"wb")as f:
for line in file_obj.chunks():
f.write(line)
return render(request,'test.html')
# 打印个别结果看看
print(request.FILES)
'''
<MultiValueDict: {'myfile': [<InMemoryUploadedFile: README.md (application/octet-stream)>]}>
'''
print(file_obj,type(file_obj))
'''
README.md <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
'''
print(file_obj.name)
'''
README.md
'''
# 官方推荐写法 chunks() 的源码
def chunks(self, chunk_size=None):
self.file.seek(0)
yield self.read()
# 一个迭代器
def func3(request):
if request.method == 'POST':
print(request.POST)
file_obj = request.FILES.get('myfile')
print(file_obj.name) # 获取文件名称
with open(r'%s'%file_obj.name,'wb') as f:
for chunks in file_obj.chunks():
f.write(chunks)
return render(request,'func3.html')
效果图:
版权声明:
作者:淘小欣
链接:https://blog.taoxiaoxin.club/158.html
来源:淘小欣的博客
文章版权归作者所有,未经允许请勿转载。

共有 0 条评论