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改訂の日付よりも後です)。このテストに合格すると、正常に認証されますが、それNone以外のすべてのビューloginでありtos_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 ビューにリダイレクトされます。それ以外の場合は、ミドルウェアが戻り、NoneDjango に通常どおりリクエストを処理し続けるように指示します。

ミドルウェアを追加するだけでMIDDLEWARE_CLASSES、あなたは金色になります。

于 2012-09-04T21:12:58.290 に答える
2

最近、クラスベースのビューとミックスインを使用して認証を行いました。例としてLoginRequiredMixindjango-bracesを見てください。

これは、(保護したい) すべてのビューに共通の mixin を含める必要があることを意味しますが、それが私が知っている最もクリーンな方法です。

使用法 ( docsから) は次のようになります。

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 に答える