Django实现请求方法和必传参数校验
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django实现请求方法和必传参数校验相关的知识,希望对你有一定的参考价值。
业务背景:
在写views控制
层的时候,需要做很多校验,判断请求类型,判断是否有必填项没传,而不同的请求类型,在代码中获取入参的方式也是不同的。
例如:
get请求 :/selectPage/?page=1&pageSize=1这种,使用 request.GET
,可以得到一个QueryDict
类型的对象,具备dict
同款的get
方法,可以通过request.GET.get('a')
的方法获取参数
post from 表单请求:/selectPage/?page=1&pageSize=1这种也可以解析,使用request.POST
post请求:对于包裹在body
下的json
格式入参数,就需要使用request.body
来获取,request.body
返回的是一个bytes类型,实际要使用还需要例如json.loads
进行转换。在这里又需要判断json.body
是否有值,需要判断json.loads
执行是否无异常,因为本身json
化就严格,经常不符合格式要求而报错
请求方法和必传参数校验器核心代码(check.py)
from functools import wraps
import json
from django.http import HttpResponse
def request_verify(request_method: str, need_params=None):
"""
在views方法上加装饰器 例如:@request_verify('get', ['id'])
:param request_method:
:param need_params:
:return:
"""
def decorator(func):
@wraps(func)
def inner(request, *args, **kwargs):
method = str(request.method).lower()
# 先判断类型,类型不符合,直接return
if request_method and not method == request_method.lower():
response = "method {0} not allowed for: {1}".format(request.method, request.path)
return response_failure(response)
request.params = {}
# 暂时不用get请求传参,get的情况可以先忽略
if method == 'get':
if not request.GET:
if need_params:
response = "缺少参数"
return response_failure(response)
else:
params = {}
request_params = request.GET
for item in request_params:
params.update({item: request_params.get(item)})
# get 必填参数校验
if need_params:
for need_param_name in need_params:
if not params.get(need_param_name):
response = "参数 {0} 不能为空".format(need_param_name)
return response_failure(response)
request.params = params
else: # method == post
if not request.body or request.body == {}: # 参数为空的情况下
if need_params: # 验证必传
response = "缺失参数"
return response_failure(response)
else: # 非空的时候,尝试去获取参数
try:
real_request_params = json.loads(request.body) # 这边要try一下,如果前端传参不是json,json.loads会异常
except Exception as e:
response = "参数格式不合法"
return response_failure(response)
# 取出来以后再去判断下必填项是否每一项都有值
if need_params:
for need_param_name in need_params:
if not real_request_params.get(need_param_name):
# 如果必传参数取出来是'' (PS: 没传和传了''通过get取出来都是''),就抛出
response = "参数 {0} 不能为空".format(need_param_name)
return response_failure(response)
# 一直到这里都无异常那么就可以把参数塞进request对象了,避免view里还要再去json.loads
request.params = real_request_params
return func(request, *args, **kwargs)
return inner
return decorator
# 校验结果封装
def response_failure(message):
return HttpResponse(json.dumps({
'code': 4000,
'message': message
}, ensure_ascii=False), 'application/json')
用法
限制请求类型:post 和get 无大小写区分
import json
from userSystem.models import Book
from django.http import HttpResponse
from django.core import serializers
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from userSystem.check import request_verify
# Create your views here.
@request_verify('get')
def select(request):
books = Book.objects.all()
for i in range(len(books)):
print("主键:%s 值:%s" % (i + 1, books[i]))
return response_success(message='后台响应成功', data_list=serializers.serialize("json", books))
@request_verify('post')
def selectAll(request):
books = Book.objects.all()
for i in range(len(books)):
print("主键:%s 值:%s" % (i + 1, books[i]))
return response_success(message='后台响应成功', data_list=serializers.serialize("json", books))
限制请求类型 + 必传参数
import json
from userSystem.models import Book
from django.http import HttpResponse
from django.core import serializers
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from userSystem.check import request_verify
@request_verify('get', ['page', 'pageSize'])
def selectPage(request):
# 当前页码
page = request.GET.get('page')
# 当前分页大小
page_size = request.GET.get('pageSize')
book_list = Book.objects.all()
# django 分页实体对象
paginator = Paginator(book_list, page_size)
# 查询总记录数
total = paginator.count
try:
# 执行分页查询
books = paginator.page(page)
except PageNotAnInteger:
# 执行分页查询,默认指定页码
books = paginator.page(1)
except EmptyPage:
# 执行分页查询,默认指定页码
books = paginator.page(paginator.num_pages)
return response_page_success(message='后台响应成功', data_list=serializers.serialize("json", books), total=total, page=page, pageSize=page_size)
@request_verify('post', ['page', 'pageSize'])
def selectPageAll(request):
json_str = request.body
json_str = json_str.decode() # python3.6及以上不用这一句代码
dict_data = json.loads(json_str) # loads把str转换为dict,dumps把dict转换为str
# 当前页码
page = dict_data.get('page')
# 当前分页大小
page_size = dict_data.get('pageSize')
book_list = Book.objects.all()
# django 分页实体对象
paginator = Paginator(book_list, page_size)
# 查询总记录数
total = paginator.count
try:
# 执行分页查询
books = paginator.page(page)
except PageNotAnInteger:
# 执行分页查询,默认指定页码
books = paginator.page(1)
except EmptyPage:
# 执行分页查询,默认指定页码
books = paginator.page(paginator.num_pages)
return response_page_success(message='后台响应成功', data_list=serializers.serialize("json", books), total=total, page=page, pageSize=page_size)
def response_success(message, data=None, data_list=[]):
return HttpResponse(json.dumps({
'code': 200,#code由前后端配合指定
'message': message,#提示信息
'data': data,#返回单个对象
'dataList': data_list#返回对象数组
}, ensure_ascii=False), 'application/json')
def response_page_success(message, data=None, data_list=[], total=None, page=None, pageSize=None):
return HttpResponse(json.dumps({
'code': 200,#code由前后端配合指定
'message': message,#提示信息
'data': data,#返回单个对象
'dataList': data_list,#返回对象数组
'total':total,#记录总数
'page':page,#当前页面
'pageSize':pageSize#当前页面分页大小
}, ensure_ascii=False), 'application/json')
效果演示:
以上是关于Django实现请求方法和必传参数校验的主要内容,如果未能解决你的问题,请参考以下文章