Decorates a Django function based view and wraps it's return in the
    :py:func:`jason.response` function. The view should return a list or tuple which is
    unpacked using the ``*``-operator into :py:func:`jason.response`.

    The view can raise a :py:class:`jason.Bail` Exception.

    ``allowed_methods`` lists which HTTP methods are allowed,
    e.g. ['GET', 'POST'].

    ``exceptions`` is a dictionary where the keys are ``Exception`` classes and
    values are callables. It defines responses for raised Exceptions other than
    the :py:class:`jason.Bail` Exception. The callable should return a tuple or list
    that can unpacked into :py:func:`jason.response`.

    Example::

        import jason

        @jason.view(allowed_methods=['GET', 'POST'], exceptions={
            WebFault: lambda e: ({}, 400, e.message, )
        })
        def my_view(request):
            return {'numbers': get_numbers()},

def view(allowed_methods, exceptions={}):
    """
    Decorates a Django function based view and wraps it's return in the
    :py:func:`jason.response` function. The view should return a list or tuple which is
    unpacked using the ``*``-operator into :py:func:`jason.response`.

    The view can raise a :py:class:`jason.Bail` Exception.

    ``allowed_methods`` lists which HTTP methods are allowed,
    e.g. ['GET', 'POST'].

    ``exceptions`` is a dictionary where the keys are ``Exception`` classes and
    values are callables. It defines responses for raised Exceptions other than
    the :py:class:`jason.Bail` Exception. The callable should return a tuple or list
    that can unpacked into :py:func:`jason.response`.

    Example::

        import jason

        @jason.view(allowed_methods=['GET', 'POST'], exceptions={
            WebFault: lambda e: ({}, 400, e.message, )
        })
        def my_view(request):
            return {'numbers': get_numbers()},
    """
    def _(f):
        def __(request, *args, **kwargs):
            if request.method not in allowed_methods:
                return response({}, 405, 'Method Not Allowed')
            try:
                return response(*f(request, *args, **kwargs))
            except Bail as e:
                return response(e.data, e.status, e.message)
            except Exception as e:
                if e.__class__ in exceptions:
                    return response(*exceptions[e.__class__](e))
                else:
                    return response({}, 500, 'Internal Server Error')
        return __
    return _