Djano探究:加工 Form 让其更适用于前后端分离

Djano探究:加工 Form 让其更适用于前后端分离,第1张

Djano探究:加工 Form 让其更适用于前后端分离
  • 关于参数验证:

在前后端发分离的大环境下,参数验证前端都会做,但后端的参数验证也必不可少,以免有人通过API输入一些恶意的极限参数,搞崩系统。

  • Django的参数验证:

Django的参数验证实际上分在两块,第一是在 url 中,你可以使用 re_path(正则路由)来过滤参数写在路由上的参数。第二就是 Django 的 表单 Form。

  •  表单对前后端分离的不友好:

因为表单最大的便捷之处是方便前后端不分离情况下模板的编写,所以在前后端分离的情况下,表单是否失去了作用呢? 实则不然,用它依旧能进行参数的验证,但只是因为表单本身是对于前后端不分离开发的,使用起来不是那么方便,返回的内容也会夹带大量的HTML结构标签,如下图:

  •  定义自己的参数验证表单要求:

1、参数出错之后,将错误信息返回给前端,如果出现多个错误,那就返回多个错误信息。

2、同时返回给前端所有参数的标准和要求,方便前端工程师调试。

3、在生产环境下这个提醒要关闭,不然不就是在指导爬虫怎么爬自己的网站了。

  • 加工表单代码:

首先,我们创建一个新的py文件,命名为baseJsonForm,在其中定义一个适用于JSON情况下的基础表单用于后续的继承,代码如下:

from django import forms
from djangoProject.settings import DEBUG


class baseJsonForm(forms.Form):

    def get_parameter_information(self):
        information_list = []
        for name in self.fields.keys():
            str_value = self[name].__str__()
            values = str_value.split(' ')
            str_value = ','.join(values[1:-1])
            information_list.append({name: str_value})
        return str(information_list).replace('"', '')

    def get_errors_information(self):
        errors = self.errors.as_json()
        errors_dict = eval(errors)
        errors_str = ''
        for key, value in errors_dict.items():
            errors_str += key + ' ' + value[0].get('message')
        return '参数错误 , ' + str(errors_str)

    def errors_information(self):
        if self.errors:
            if DEBUG:
                parameter_information = '参数详情 : ' + self.get_parameter_information()
                msg = self.get_errors_information()
            else:
                parameter_information = []
                msg = '参数异常。'
            data = {'msg': msg, 'code': 420, 'data': parameter_information}
            return data
        else:
            return None

第二,继承该基础类,编写自己的过滤函数的过滤要求,演示代码如下:

from django import forms
from djangoProject.baseJsonForm import baseJsonForm


class TestViewRestForm(baseJsonForm):
    name_id = forms.IntegerField(min_value=0, max_value=2,
                                 error_messages={'required': '该值不能为空,应该是大于0,小于或等于2的正整数。',
                                                 'invalid': '输入格式错误,应该是大于0,小于或等于2的正整数。'})
    payment = forms.IntegerField(min_value=0, max_value=10000,
                                 error_messages={'required': '该值不能为空,应该是大于0,小于或等于10000的正整数。'})

第三,修改你的视图函数,代码如下:

from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from user.form import TestViewRestForm

class TestViewRest(APIView):

    def get(self, request):
        form = TestViewRestForm(request.GET)
        if not form.is_valid():
            return JsonResponse(data=form.errors_information(), status=420)
        else:
            name_id = form.cleaned_data.get("name_id")
            payment = form.cleaned_data.get('payment')
        result = Vocation.objects.filter(name=name_id, payment__lt=payment)
        serializer = MySerializer(instance=result, many=True)
        return Response(serializer.data)
  • 测试:

我们定义了两个验证要求,第一个是name_id不能为空,整数,且必须要大于0,小于或等于2。

第二个是payment,不能为空,整数,且必须要大于0,小于或等于10000。

我们使用 postman 试试好不好用,填入一个超过范围的 name_id,和一个空的 payment :

显然依旧达到了我们的要求,这里解释下参数详情中的 required 意味必须的,就是不能为空,这是Django Form 自己定义的,你可以根据自己的习惯改。状态码也是我自己随手写的,这个可以跟前端协商规定。

接下来输入正常的值看看结果:

OK,非常的完美,我们可以利用表单的强大的验证功能,编写复杂的过滤要求,同时又能直观的通过JSON把错误反馈给前端。

对了,最后一个要求,生产环境下不反馈有效信息。在重写的过程中,我识别了 settings 中 DEBUG,如果关闭了DEBUG,那么就不会再返回任何有价值的信息,如下:

内容就到这里,代码原理我不解释了,需要去看 Django Form 的源码,不然我解释半天,你也不知大我说了些啥,有兴趣的小伙伴可以自己对着研究下。我也是看了半天搞懂了逻辑,才改写出来的,好东西跟大家一起分享,如果你觉得有用,可以点个赞再走。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5689379.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存