创建Django作出反应的自定义异常

T. *_*one 15 django

对于我的网站,我创建了一个抽象模型,它实现了模型级读取权限.系统的该部分已完成并正常运行.许可模型公开的方法之一是is_safe(user)可以手动测试是否允许用户查看该模型.

我想要做的是添加一个方法continue_if_safe,可以在任何模型实例上调用其效果,而不是返回一个布尔值,就像is_safe它首先测试是否可以查看模型,然后在False的情况下,它会将用户重定向到登录页面(如果他们尚未登录)或者如果他们已登录则返回403错误.

理想用途:

model = get_object_or_404(Model, slug=slug)
model.continue_if_safe(request.user)
# ... remainder of code to be run if it's safe down here ...
Run Code Online (Sandbox Code Playgroud)

我偷看了get_object_or_404是如何工作的,它抛出了一个Http404似乎有意义的错误.但是,问题是似乎没有等效的重定向或403错误.最好的方法是什么?

(非工作)continue_if_safe方法:

def continue_if_safe(self, user):

    if not self.is_safe(user):
        if user.is_authenticated():
            raise HttpResponseForbidden()
        else:
            raise HttpResponseRedirect('/account/')

    return
Run Code Online (Sandbox Code Playgroud)

编辑 - 解决方案

最终解决方案的代码,以防其他"堆栈器"需要一些帮助:

在抽象模型中:

def continue_if_safe(self, user):
    if not self.is_safe(user):
        raise PermissionDenied()
    return
Run Code Online (Sandbox Code Playgroud)

中间件捕获视图:

class PermissionDeniedToLoginMiddleware(object):
    def process_exception(self, request, exception):
        if type(exception) == PermissionDenied:
            if not request.user.is_authenticated():
                return HttpResponseRedirect('/account/?next=' + request.path)
        return None
Run Code Online (Sandbox Code Playgroud)

视图中的用法(非常简短和甜蜜):

model = get_object_or_404(Model, slug=slug)
model.continue_if_safe(request.user)
Run Code Online (Sandbox Code Playgroud)

Clé*_*ent 10

对于禁止(403)错误,您可以引发PermissionDenied异常(from django.core.exceptions).

对于重定向行为,没有内置的方法来处理您在问题中描述的方式.您可以编写一个自定义中间件来捕获您的异常并重定向process_exception.


Jon*_*gat 5

我做了一个小的中间件,它返回你的Exception类的render方法返回的内容.现在,您可以在任何视图中抛出自定义异常(使用渲染方法).

class ProductNotFound(Exception):
    def render(self, request):
        return HttpResponse("You could ofcourse use render_to_response or any response object")
Run Code Online (Sandbox Code Playgroud)
pip install -e git+http://github.com/jonasgeiregat/django-excepted.git#egg=django_excepted
Run Code Online (Sandbox Code Playgroud)

并添加django_excepted.middleware.ExceptionHandlingMiddleware到您的MIDDLEWARE_CLASSES.