如何使用装饰器来验证请求并继续执行其他抛出错误

时间:2017-01-04 11:51:21

标签: python django decorator

我想知道如何使用装饰器来验证django中的JSON请求。目前我有validations.py文件,函数validate如果请求有效则返回True,否则返回False

我目前的实施方式如下:

validations.py:

def validate(request):
   flag = True
   .... # Actual logic for validating request and 
        # sets flag to True/False
   return flag

views.py

from validations import validate

def authenticate_user(request):
     if validate(request):
        .......
        # executes further logic based on request
        # This checks if right access is present in Database
        # for the user or not. And hence I want to access request variable as it is
     else:
        return "Bad Request"

我想知道我在这里如何使用装饰器并做这样的事情:

@validate
def authenticate_user(request):
    .......
    # executes further logic based on request
    # This checks if right access is present in Database
    # for the user or not. And hence I want to access request variable as it is

validate函数应该直接将"Bad Request"返回给客户端,如果验证因任何原因而失败,则应该执行正常的代码执行。

3 个答案:

答案 0 :(得分:1)

您可以执行类似

的操作
import inspect

def decorator(f):

    def requestchecker(request, *args):
        if not validate(request):
            raise ValueError("bad request")
        return f(request, *args)
    return requestchecker


@decorator
def djangoview(request, x, y):
    # do stuff

当然,应该稍微修改实际代码,具体取决于您是使用命名还是位置等...

答案 1 :(得分:1)

第一点:你的验证函数不应该返回一个布尔标志(它不会告诉你什么出错),而是引发异常(可能是ValidationError或你自己的自定义异常类型,具体取决于你的'确切地重新验证 - 调用者负责捕获它并做适当的事情。

第二点:您的视图不应返回文字字符串“Bad request”,它应返回带有相应状态代码的HttpResponse。 FWIW,“错误请求”的http状态代码是400,但它有一个非常明确的语义(强调是我的):

  

由于格式错误,服务器无法理解该请求   语法即可。客户端不应该重复请求   修改

JSON有效负载中缺少的字段不是“格式错误的语法”。

至于如何使用装饰器将相同的验证函数应用于多个视图函数,假设validate函数引发ValidationError(或您定义的任何更具体的异常类型):

def require_validation(func):
   def wrapper(request, *args, **kwargs):
        try:
            validate(request)
        except ValidationError as e:
            # logging the exception might be useful
            # and you may want to select the exact
            # response status depending on the exact error
            # Also if your client posted some json stuff
            # chances are it expects a json content-type and body
            return HttpResponse("Bad request", status=400)

        return function(request, *args, **kwargs)

    wrapper.__doc__ = function.__doc__
    wrapper.__name__ = function.__name__
    return wrapper

@require_validation
def myview(request, ...):
    #...

答案 2 :(得分:0)

你也可以这样做..

from yourmodel.models import Admin
from django.http import HttpResponseRedirect

def admin_required(function):
    """
    @admin_required
    def dashboard(request):
        #do_stuff
    """
    def wrap(request, *args, **kwargs):
        if request.user.is_authenticated() and \
                Admin.objects.filter(user=request.user).exists():
            return function(request, *args, **kwargs)
        else:
            return HttpResponseRedirect('/')
    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap