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('点我有惊喜')

image-20210504212752984

request.GET

  • 可以看成一个字典

  • 有相同的键,就把所有的值放到对应的列表里。

  • 取值格式:对象.方法

  • get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。

  • getlist():获取整个列表

示例:

def test(request):
    # name = request.GET.get('name')
    name = request.GET.getlist('name')
    return HttpResponse(f'{name}')

image-20210504231055163

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>")

image-20210504223449710

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。

image-20210324152659051

为什么必须要返回这个对象呢?我们 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类

image-20210324161433755

image-20210324161602540

image-20210324161717693

小结:

响应对象

  • 响应对象主要有三种形式: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格式

image-20210324164446224

2.2 使用JsonResponse对象

def func2(request):
    user_info = {'user': 'shawn', 'password': 1313, 'sex': '男', 'hobby': '吃泔水'}
    return JsonResponse(user_info)

image-20210324171934247

问题:JsonResponse 对象没有 ensure_ascii 参数来保证中文正常显示吗?

首先,我们来查看源码。

image-20210324183833403

由源码可知,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  # 看报错信息

效果如下:

image-20210324184810054

再来思考,如果是一个列表呢?怎么去序列化?

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.

image-20210324185200721

提示为了让非字典对象能够被序列化,设置safe参数为false。

我代码没有写这个啊,这是哪来的呢?

凭空捏造??且看JsonResonse源代码

image-20210324185848674

加入 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表单上传文件注意事项

  1. method必须是post
  2. 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')

效果图:

image-20210317222610019

版权声明:
作者:淘小欣
链接:https://blog.taoxiaoxin.club/158.html
来源:淘小欣的博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
Django 视图请求对象与相应对象,forms文件上传
一、视图函数 视图层介绍 一个视图函数,简称视图,是一个简单的 Python 函数,它接受 Web 请求并且返回 Web 响应。 响应可以是一个 HTML 页面、一个 404 错误……
<<上一篇
下一篇>>