使django支持PUT,DELETE的方案

第一种方案

修改ajax中type方式并设置header,同时对put重新构建数据字典

在对views中的方法进行类对象封装时,发现django并不支持像post和get一样将数据封装。
由于网页端无法设置method方法,在用postman和ajax开启pycharm对接口进行debug测试时发现:提交数据后并没有进入代码逻辑。
查阅资料得知,django支持put和delete方法。
为了防止跨站攻击,Django默认会对POST/PUT/DELETE这几种操作进行csrf token检查。POST可以将其放到post的参数中,但Django对PUT/DELETE只能通过检查Header的方式检查csrf token。
所以在进行ajax发送表单数据时,需要在ajax头文件中设置csrf
测试代码段如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<form action="">
    {% csrf_token %}
    用户名:<input type="text" name="username" id="username">
</form>
<button type="button" id="btn">提交</button>
<span id="spa"></span>
</body>
</html>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<script>
    $('#btn').click(function () {
        var username = $('#username').val();
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        $.ajax({
            type:'PUT',
            url: '/test/',
            data: {
                'username':username
            },
            dataType: 'JSON',
            success: function (data) {
                $('#spa').text('成功')
            }
        })
    })
</script>
from django.views.generic import View

class TestView(View):
    def get(self,request):
        return render(request,'test.html')
    def put(self,request):
        pass

同时django对于PUT/DELETE请求并没有像POST/GET那样有一个字典结构。我们需要手动处理request.body获取参数:

from django.http import QueryDict
    put = QueryDict(request.body)
    key = put.get('key')
    field = put.get('field')
    field_value = put.get('field-value')

put构造字典代码片段来源于简书:吃土的汉子
上述办法put设置header中的csrf验证通过,进入代码逻辑


第二种方法

使用django-restframework模块
pip install djangorestframework
pip install markdown       # Markdown support for the browsable API.
pip install django-filter  # Filtering support

同时在settings.py中设置

INSTALLED_APPS = (
    ...
    'rest_framework',
)

django-restframework方案并未测试,在测试后会反馈更新


第三种方法

在前端header中构造x-method字段,在中间件中进行验证,在前端使用put,delete方法时,采用post方式打包数据,但通过中间件进行method 数据打包转移
util.py中设置json返回值

首先设置json返回值

import json

from django.http.response import HttpResponse

def params_error(data):
    return HttpResponse(json.dumps({
        'status': 422,
        'data': data
    }))
middleware设置解析方法
import json

from django.utils.deprecation import MiddlewareMixin
from django.http.multipartparser import MultiPartParser

from .utils import params_error

class MethodConvertMiddleware(MiddlewareMixin):
    '''
    自定义method方法
    '''
    def process_request(self,request):
        method = request.method
        '''
        判断数据类型,对数据进行封装
        '''
        #判断是否为ajax提交方式
        if 'application/json' in request.META['CONTENT_TYPE']:
            try:
                data = json.loads(request.body.decode())
                files = None
            except Exception as e:
                return params_error({
                    'msg': '请求数据格式错误'
                })
        #判断是否为form提交方式
        elif 'multipart/form-data' in request.META['CONTENT_TYPE']:
            data,files = MultiPartParser(
                request,request.META,request.META.upload_handlers
            ).parse()
        #否则为get提交方式
        elif:
            data = request.GET
            files = None
        #判断前端传来的headers中是否含自定义字段
        if 'HTTP_X_METHOD' in request.META:
            #对ajax传入的方法进行字母格式控制
            method = request.META['HTTP_X_META'].upper()
            #给request对象赋于method属性
            setattr(request,'method',method)
        #判断是否有文件上传
        if files:
            setattr(request,'{method}_FILES'.format(method=method),files)
        #将data数据添加到method中
        setattr(request,method,data)

在通过对中间件进行设置后,无需使用ajax在提交的request头部放入csrf信息,只需使用post提交方式,自定义’HTTP_X_METHOD’字段为put或delete,即可实现django对put和delete的支持

如有疑问请留言或访问博主个人微博
个人博客地址

猜你喜欢

转载自blog.csdn.net/weixin_35993084/article/details/80778921
今日推荐