4

我正在向我们的网站添加服务条款接受要求,并试图找出在Django 身份验证框架内处理此问题的最佳方法。

为简单起见,这里有一个UserProfile模型:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    accepted_tos_at = models.DateTimeField(default=None, editable=False, null=True)

所以基本上我想要做的是检查它accepted_tos_at不是None(或者实际上大于最后一次 TOS 修订的日期)。如果它通过了这个测试,那么我们就可以正常进行身份验证,但是如果它是Nonelogintos_display不可访问的所有视图。

我挂断的是你应该如何在全球范围内做这件事?我不想在我的每一个视图中添加user_passes_test装饰器,同样我想避免在我的每一个视图中测试这个权限。必须有更清洁的方法。

4

2 回答 2

8

通常,当您谈论应该适用于每个视图的东西时,您就是在谈论中间件。在您的情况下,这是相对简单的:

class AcceptTOSMiddleware(object):
    def process_request(request):
        login_url = reverse('login')
        tos_url = reverse('tos_display')
        if request.path not in [login_url, tos_url]:
            profile = request.user.get_profile()
            if profile.accepted_tos_at is None or \
               profile.accepted_tos_at < settings.LAST_TOS_REVISION:
                return HttpResponseRedirect(tos_url)
        return None

首先,这会检查请求的 URL 是否不是登录或 TOS 视图。如果需要重定向,这可以防止无限循环。然后,您检查accepted_tos_at. 我假设您只是将上次修订日期存储为设置,因此如果您有其他计划,则需要对其进行修改。如果需要接受 TOS,则将用户重定向到 TOS 视图,否则,中间件返回None,告诉 Django 继续正常处理请求。

只需添加中间件MIDDLEWARE_CLASSES,你就可以了。

于 2012-09-04T21:12:58.290 回答
2

我最近使用基于类的视图和 mixin 完成了身份验证。以django-braces为例LoginRequiredMixin

这确实意味着您的所有视图(您想要保护的)都需要包含一个通用的 mixin,但这是我所知道的最干净的方式。

用法(来自文档)是这样的:

from django.views.generic import TemplateView
from braces.views import LoginRequiredMixin


class SomeSecretView(LoginRequiredMixin, TemplateView):
    template_name = "path/to/template.html"

    def get(self, request):
        return self.render_to_response({})

您可能想要定义自己的 mixin,它可能看起来像这样(未经测试):

class AcceptedTOSRequiredMixin(object):
    def dispatch(self, request, *args, **kwargs):
        profile = request.user.get_profile()

        if not profile or profile.accepted_tos_at is None:
            return HttpResponseForbidden()  # return a forbidden response.

        return super(AcceptedTOSRequiredMixin, self).dispatch(request,
                     *args, **kwargs)

其他方法涉及在 URL 级别装饰它们,但在我看来这更丑陋(如果有帮助的话,我很乐意挖掘它的外观示例)。

于 2012-09-04T20:33:24.237 回答