我想知道是否有一种python hack的方法来实现以下目标:
我发现自己在视图中经常使用类似断言的结构:
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函数的结果永远不会返回。此外,我还需要将Response一直返回到视图函数并运行return verify()
,这当然会使我的代码无法执行。
一个可能的解决方案是一个装饰器,它要么返回一个错误,要么在所有断言都通过后返回视图函数。然而,我希望防止这种情况发生,因为我还需要一些我正在建立的值(想象一下解析一个接一个的数字,然后必须传递一个数字列表)。
我能想到的另一个解决方案是实际使用装饰器并使我的函数成为生成器,产生验证的结果。装饰器是在生成器上的一个循环,直到产生响应为止。
但是在这篇文章中,我真的在寻找一种更hack的方法,让嵌套函数返回一个响应而不是父函数,从而防止执行。
我将在一个单独的答案中发布我的产量"解决方案",以便您可以获得图片:)
如果出现一个异常,并使用一个漂亮的装饰器来捕获它呢:
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")
这里我给出了基于生成器的解决方案:
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!")