Search code examples
pythondjangoassert

Django: views and assert like returns


I wonder if there is a python hackish way to achieve the following:

I found myself using an assert like structure in my views a lot:

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

    if not condition2:
        return HttpResponseServerError("error2")

    [...]

    return HttpResponse("OK!")

So I thought about using an assert like function:

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")

Obviously, this does not work, as the result of the error function is never returned. Furthermore, I would also need to return the Response all the way to the view function and run return verify(), which will make my code prevent from execution of course.

One possible solution would be a decorator that either returns an error or the view function after all asserts went through. However, I would like to prevent that, as I also need some of the values I am establishing (imagine parsing one number after another and then having to pass a list of numbers).

Another solution I could think of is to actually do use a decorator and make my function a generator, yielding the result of verify. The decorator is a loop over that generator and keeps going until a response is yielded.

But in this post I am really looking for a more hackish way, to let the nested function return a reponse instead of the parent function and therefore prevent execution.

I will post my yield "solution" in a separate answer so you can get the picture :)


Solution

  • What about an exception, and a nice decorator to catch it:

    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")