Python Django:类似于视图和断言的返回

Python Django:类似于视图和断言的返回,python,django,assert,Python,Django,Assert,我想知道是否有一种python黑客方法可以实现以下目标: 我发现自己在视图中经常使用类似断言的结构: def view(request): if not condition: return HttpResponseServerError("error") if not condition2: return HttpResponseServerError("error2") [...] return HttpResponse("

我想知道是否有一种python黑客方法可以实现以下目标:

我发现自己在视图中经常使用类似断言的结构:

def view(request):
    if not condition:
        return HttpResponseServerError("error")

    if not condition2:
        return HttpResponseServerError("error2")

    [...]

    return HttpResponse("OK!")
所以我考虑使用类似断言的函数:

def view(request):
    def err(msg=None):
        msg = msg if msg else "Illegal Parameters"
        resp = {"msg": msg}
        resp = json.dumps(resp)
        return HttpResponseServerError(resp)

    def verify(exp, msg=None):
        if not exp:
            err(msg)

    verify(condition, "error")

    verify(condition2, "error2")

    return HttpResponse("OK")
显然,这不起作用,因为永远不会返回error函数的结果。此外,我还需要将响应返回到view函数,并运行
return verify()
,这当然会阻止代码执行

一种可能的解决方案是在所有断言完成后返回错误或视图函数的装饰器。但是,我想避免这种情况,因为我还需要一些我正在建立的值(想象一下解析一个又一个数字,然后必须传递一个数字列表)

我能想到的另一个解决方案是实际使用一个装饰器,将我的函数变成一个生成器,生成验证结果。装饰器是该生成器上的一个循环,并一直运行,直到生成响应为止

但在这篇文章中,我真的在寻找一种更老练的方法,让嵌套函数返回一个响应,而不是父函数,从而阻止执行


我将在一个单独的答案中发布我的收益率“解决方案”,这样您就可以得到图片:)

这里我介绍基于生成器的解决方案:

def assertLike(view):
    def wrap(request, *args, **kwargs):
        for response in view(request, *args, **kwargs):
            if response:
                return response
    return wrap


@other_django_views
@another_django_view
@assertLike
def createTask(request):
    import json

    def err(msg=None):
        msg = msg if msg else "Illegal Parameters"
        resp = {"msg": msg}
        resp = json.dumps(resp)
        return HttpResponseServerError(resp)

    def verify(exp, msg=None):
        if not exp:
            return err(msg)

    # only react to ajax requests
    yield verify(True, "This is not an error")
    yield verify(False, "Here it should stop!")

    yield HttpResponse("This is the final response!")

一个异常和一个很好的装饰程序如何捕捉它:

class AssertError(Exception):
    pass

def assertLike(view):
    def wrap(request, *args, **kwargs):
        try:
            return view(request, *args, **kwargs):
        except AssertError as e:
            return HttpResponseServerError(...)
    return wrap

@assertLike
def createTask(request):
    import json
    ....
    if not exp:
        raise AssertError()
    ....
    return HttpResponse("Ok")

为什么不例外?例如,我想这就是
get\u object\u或\u 404()
的实现方式。我现在想用棍子打自己…@rodrigo然而,如果你真的抛出一个异常,它会限制你的可能性,除非你捕捉到它(在装饰程序中可能是xP)。例如,如果我想返回一个正确的JSON响应,其中只包含一个
错误:True
。是的,如果有多个视图需要执行此操作,则可以使用decorator。如果只是一种观点,那就不值得了。在这里,我添加了一个答案,把所有的观点放在一起。我没有测试它,所以把它当作草图。我真的很喜欢这个主意。比我的好,因为它清除了大量使用yield的语法。我考虑在一个模块中实现它,它允许一个适当的异常,允许传递响应!