- 关于参数验证:
在前后端发分离的大环境下,参数验证前端都会做,但后端的参数验证也必不可少,以免有人通过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 的源码,不然我解释半天,你也不知大我说了些啥,有兴趣的小伙伴可以自己对着研究下。我也是看了半天搞懂了逻辑,才改写出来的,好东西跟大家一起分享,如果你觉得有用,可以点个赞再走。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)