当前位置: 首页>后端>正文

django restframework 设置请求解析器 django解析json

内部解析机制

我们的Django框架或者html" class="superseo">ajax内部都有一个json的解析机制,可以帮助我们解析json数据,让我们省去使用json.dumps或者JSON.parse等方法进行相应的解析。

  • ajax的js解析机制
views函数:
通过HttpResponse给前端响应数据时,加上一个content_pe='application/json'这样的头部键值对
return HttpResponse(ret_dict_json, content='application/json')


ajax:
获得res直接就是一个object对象(字典),因为通过这个头部可以调用ajax的json内部解析机制对其进行解析,省去了JSON.parse(res)这个环节。
  • Django的json解析机制
from django.http import JsonResponse
# JsonResponse 将一个数据内部转化成Json的格式,响应给前端
# 这样我们就省去了json.dumps这个环节
ret_dict = {'code':0, 'content': '用户名或者密码错误'}
return JsonRespone(ret_dict)
  • 尝试一个列表
    html:
{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initialscale=1">
    <title>Bootstrap 101 Template</title>
</head>

<body>
    <h3>欢迎来到ajaxlx⾸⻚</h3>
    <ul>
    </ul>
</body>
<script src="{% static 'jQuery.js' %}"></script>
<script>
    $.ajax({
        url: "{% url 'data' %}",
        type: 'get',
        success: function (res) {
            {#console.log(res, typeof res)# }
            {#var li = '<li>' + res + '</li>'# }
            $.each(res, function (k, v) {
                var li = '<li>' + v + '</li>';
                $('ul').append(li)
            })
        }
    })
</script>

</html>

views函数:

def ajax_lx(request):
    return render(request, 'lx.html')
    
def data(request):
    l1 = ['姓名1', '姓名2', '姓名3']
    # 我们通过网络传输数据一般都是字段类型,前端教object类型。
    #In order to allow non-dict objects to be serialized set the safe
parameter to False.
    return JsonResphonse(l1, safe=False)

url:

url(r'^ajaxlx/', views.ajax_lx,name='ajaxlx'),
url(r'^data/', views.data,name='data'),

 

 

content-type

这个参数比较重要,这个参数是请求头部信息中,非常重要的参数,这个参数是标明请求参数的数据类型。

  • content-type = application/x-www-form-urlencoded
    我们简称encoded类型,一般前端给后端发送数据(get。post),form、ajax等方式默认一般都是encoded类型。
    通过ajax提交数据:

通过form表单提交:

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_json,第1张

这种类型的原始数据是神样子的?

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_ajax_02,第2张

无论是ajax还是form(无论是get还是post)或者其他方式,只要是encoded类型,原始数据都是:

键=值&键=值&键=值...

为什么浏览器会同意这种格式?

浏览器统一了请求数据的格式,便于后端做归一化处理。

看我们的Django后端:

为什么我们通过request.POST.get(键)或者request.GET.get(键)就可以获取该值?

就是因为Django的内部解析器帮助我们做了请求数据的解析:
举例:
Django的内部做了一个这样的判断:
if 'content_type' == 'application/x-www-form-urlencoded':

'''uname=taibai&pwd=123&csrfmiddlewaretoken=oTRcxqSxLGSygOSaMrqyiakOXJIgbM
CBVAESFZ1dqK8ttsHL9maoI9wzLEyfYcaI
 '''    
通过&分割,然后在通过等号分割,然后构建到request.POST或者request.GET中,最终我们可以通过get方法获取到对应值。

 

  • content_type = application/json
    Django框架默认不认可这种类型,这就意味着,如果我们与其他的一些程序员或者一些语言写的项目对接数据,这就叫做数据接口,一般这种数据接口都是使用这种数据类型。content_type = application/json类型
    验证一下:

这样我们就构建了以application/json的类型的json数据,发送到Django框架的后端。

后端默认取不到对应的值,返回的是None

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_ajax_03,第3张

只能通过:

request.get_full_path()  # 获取原始数据

这样我们只能自己完成数据的分割以及获取

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_html_04,第4张

我们通过request.META获取conten_type内容,判断如果是application/json类型我们自己在后端对request.get_full_path()进行数据切割,从而获取数据。但是这样给我们增加了开发难度,降低开发效率。这种情况下,有一个第三方模块:*前后端分离的模块,djangorestframework

 

  • content_type = mutipart/form-data类型
    给Django后端发送的请求数据为文件(文本、图片、视频、音频等等),是这种类型,
    Django内部解析器可以帮我们解析。
    (下面综合文件上传一起)

 

文件上传

  • form表单
def form_upload(request):
    if request.method == 'GET':
        return render(request, 'formupload.html')
    else:
        # print(request.POST)
        '''
 <QueryDict: {'csrfmiddlewaretoken':
['8FUYSNC9tTfsVpGzHSJlz7s7Lkko1U12FmHE0mLP8Xvn83va4NtbZ6ESzfanOkz9'],
 'head_pic': ['barry.png'],
 'ID': ['1232321321321321']}>
        '''
        # print(request.POST.get('ID'))
        # ret = request.POST.get('head_pic') # 获取了⽂件的⽂件名
        # print(ret, type(ret))
        
        # file = request.FILES # <MultiValueDict: {}>
        # 为什么是空?因为from表单没有规定enctype属性
        # < MultiValueDict: {'head_pic': [ < InMemoryUploadedFile: barry.png(image / png) >]} >
        # 这个文件数据是一个迭代器,类似于文件的文件句柄
        # print(file)
        
        
        # file_obj = request.FILES.get('head_pic')
        # print(file_obj)  # 返回的是名字  因为__str__返回的是名字
        # print(file_obj.name) # 获取的是名字
        
        file_obj = request.FILES.get('head_pic')
        from ajac_online import settings
        import os
        img_path = os.path.join(settings.BASE_DIR,'statics','img')
        # 方式1:
        # with open(os.path.join(img_path, file_obj.name), mode='wb') as fp:
            # for line in file_obj:
                # 默认按照行去循环,以换行符/r/n为循环节点
            #   fp.write(line)
            
        # 方式2:
        with open(os.path.join(img_path, file_obj.name), mode='wb') as fp:
            for chunk in file_obj.chunks():
                f1.write(chunk)
        return redirect('formupload')
                
        
        

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>
</head>

<body>
    <h1>form表单⽂件上传</h1>
    <form action="" method="post" enctype="multipart/form-data">
        {# 这个属性就是规定的content_type类型 #}
        {% csrf_token %}
        头像:<input type="file" name="head_pic">
        <p></p>
        身份证:<input type="text" name="ID">
        <p></p
  • 自己写的:
    url:
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^wenjianshagnchuan1/', views.shangchuan1, name='file_sc_form')
]

html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>form表单文件上传</h1>
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    文件:<input type="file" name="file_form_sc">
    <p></p>
    ID:<input type="text" name="ID">
    <p></p>
    <input type="submit">
</form>
</body>
</html>

views:

def shangchuan1(request):

    if request.method == 'GET':
        return render(request, 'file_sc.html')
    else:
        file_obj = request.FILES.get('file_form_sc')
        import os
        from ajax_practice1 import settings
        # 注意:需要提前在静态文件夹里面创建好 images 文件夹
        img_path = os.path.join(settings.BASE_DIR, 'jingtaiwenjian', 'images')
        with open(os.path.join(img_path, file_obj.name), mode='wb') as fp:
            for chunk in file_obj.chunks():
                fp.write(chunk)
        print(file_obj.name, '保存完成!')
        return redirect('file_sc_form')

  

  • ajax文件上传
    1、重新启动一个流程
    2、构建代码
    url:
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^wenjianshangchuan2/', views.shangchuan2, name='file_sc_ajax'),
]

views:

from django.shortcuts import render, redirect, HttpResponse
from django.views import View
import json


def shangchuan2(request):

    if request.method == 'GET':
        return render(request, 'file_sc_ajax.html')
    else:
        print(request.POST)
        print(request.POST.get('ID'))
        print(request.FILES)
        print(request.FILES.get('file_ajax_sc'))

html:

{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>ajax文件上传</h1>
</body>
<div>
    {% csrf_token %}
    文件:<input type="file" id="file_ajax_sc">
    <p></p>
    ID: <input type="text" id="ID">
    <p></p>
    <input type="button" value="提交" id="btn">
</div>
<script src="{% static 'jquery-3.5.1.js' %}"></script>
<script>
    $('#btn').click(
        function () {
            $.ajax(
                {
                    url: "{% url 'file_sc_ajax' %}",
                    type:'post',
                    data:{
                        file_ajax_sc: $('#file_ajax_sc').val(),
                        ID : $('#ID').val(),
                        csrfmiddlewaretoken: '{{ csrf_token }}'
                    },
                    success : function (res) {
                        console.log(res)
                    }
                }
            )
        }
    )
</script>
</html>

上面这种方式。只能提交非文件的数据,不能提交文件类的数据

3、重构代码

  • 如何获取文件数据
    通过之前的构建方式,你只是获取了文件的路径,而并没有文件的数据。
    jQuery对象与DOM对象的互相转换
jQuery对象 ——》 DOM对象:
    $('')[0]
    
DOM对象 ——》 jQuery对象
$(DOM)

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_json_05,第5张

DOM对象.files 返回文件列表

views代码:

def shangchuan2(request):

    if request.method == 'GET':
        return render(request, 'file_sc_ajax.html')
    else:
        file_obj = request.FILES.get('file_ajax_sc')
        import os
        from ajax_practice1 import settings
        img_path = os.path.join(settings.BASE_DIR, 'jingtaiwenjian', 'images')
        print(img_path)
        with open(os.path.join(img_path, file_obj.name), mode='wb') as fp:
            for chunk in file_obj.chunks():
                fp.write(chunk)
        print(file_obj.name, '保存完成!')

        return HttpResponse('请求成功')

html:

{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>ajax文件上传</h1>
</body>
<div>
    {% csrf_token %}
    文件:<input type="file" id="file_ajax_sc">
    <p></p>
    ID: <input type="text" id="ID">
    <p></p>
    <input type="button" value="提交" id="btn">
</div>
<script src="{% static 'jquery-3.5.1.js' %}"></script>
<script>
    $('#btn').click(
        function () {

            var formdata = new FormData();
            formdata.append('ID', $('#ID').val());
            formdata.append('file_ajax_sc', $('#file_ajax_sc')[0].files[0]);
            formdata.append('csrfmiddlewaretoken','{{ csrf_token }}');

            $.ajax(
                {
                    // 要通过ajax上传文件数据必须借助于formdata对象进行上传
                    url: "{% url 'file_sc_ajax' %}",
                    type:'post',
                    data : formdata,
                    processData: false,  // 不处理数据
                    contentType: false, // 设置数据类型
                    success : function (res) {
                        console.log(res)
                    }
                }
            )
        }
    )
</script>
</html>

 

 

 

settings配置文件

项目中的settings是Django提供给用户进行配置的,删掉settings默认配置的某些元素,你的整个项目是不影响的。为什么?

Django的源码中有一个框架的内部settings。启动项目,先加载给用户设置的settings文件,然后再加载源码中的内置的settings文件。

from django.conf import settings

按住ctrl+鼠标点击settings。然后在ctrl+鼠标单击global_settings

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_json_06,第6张

 

 

如果想要更改全局的settings,你可以直接更改在全局settings里面更改,也可以在用户的settings里面复制更改。

 

json的回顾

json是一个语言,但是他更像是一个公认的转换格式。所有语言都支持的一种转化格式。

django restframework 设置请求解析器 django解析json,django restframework 设置请求解析器 django解析json_json_07,第7张

 

 

python中的set集合,就不能发送给js,因为json就不可能让你set序列化。

带来的我呢提,前端和后端会经常交互一些时间数据,pthon有date以及datetime类型,jsono中没有响应的数据,默认i情况下,后端要想给前端发送一个date或者datetime类型的数据,是发送不出去的。

测试:

import json
from datetime import datetime
from datetime import date


class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field, date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONDecodeError.default(self, field)

ret = {'name': 'dong', 'birthday': datetime.now()}

dd = json.dumps(ret, cls=JsonCustomEncoder)
print(dd)

 

 

http协议回顾

http是超文本传输协议,浏览器与服务端进行数据通信要遵循的协议。

http协议有三个特点:基于请求与响应,无连接,无状态

  • 什么是会话?
    http协议是不支持绘画的这种模式的。因为http是无连接无状态的。
  • 无连接
    无连接(短连接),浏览器请求一个页面,与服务端建立一个连接,服务端收到请求返回给浏览器一个页面,连接断开。为什么要断开?建立一个连接服务端要开启一个线程处理,非常耗费资源,最早都是无连接的,现在有的可以设置为短链接,建立连接之后,保持一段时间,默认是3秒钟,这个时间你可以控制。

浏览一个网站用户会保持一段时间,在这个时间之内,保持连接比断开在连接效率要高一些。

  • 无状态
    一个用户访问一个网站,通过http协议,那么http协议不会记住你这个用户的信息,你链接一次断开了,再次连接,http不会记住你。这激素和i无状态。
  • 带来的影响:
    比如我们访问淘宝,当你想访问购物车时,先登录,在访问,然后访问收藏夹的时候,还得登录,才能访问,在访问其他界面,还得先登录...
    这样用户体验感好不好?
    肯定不好,你如果想完成访问你的网站,登录一次之后,网站所有的页面都可以访问了这样的需求,这样http协议完不成了,你需要借助cookie与sesstion了。

https://www.xamrdz.com/backend/39e1938719.html

相关文章: