web-dev-qa-db-ja.com

すべてのページをグローバルにログインを要求するように設定しますか?

認証されていないユーザーのアクセスをログインページにリダイレクトしたいのですが、その後、ログインしたユーザーは最初に要求されたページにリダイレクトされます。

ドキュメントによると、これは@user_passes_testデコレータを使用して簡単に実現できます。しかし、私はすべてのビューを装飾する必要があるようです。これはクレイジーで、多すぎてエラーが発生しやすくなります。

この機能をグローバルにオンにする良い方法は何ですか(loginなどの小さな固定ビューセットを除く)?つまり、すべてをデフォルトでログインのみに設定し、必要に応じて匿名表示を明示的に処理します。

34
user1067863
from Django.shortcuts import redirect
from Django.conf import settings


class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.login_url = settings.LOGIN_URL
        self.open_urls = [self.login_url] + \
                         getattr(settings, 'OPEN_URLS', [])

    def __call__(self, request):
        if not request.user.is_authenticated \
        and not request.path_info in self.open_urls:
            return redirect(self.login_url+'?next='+request.path)

        return self.get_response(request)
3
tulsluper

私がこれを解決した方法は、デコレータ(または必要なコード)を使用してミックスインクラスを作成することでした。 super(Class, self).get(...)関数を呼び出すことを覚えておく必要がありますが、結局のところそれほど違いはないと思います。

一方、私が見つけたさまざまなことを実行するミックスインのセットを持つことは、多くのコードなしで多くのことを実行するための非常に単純なビューを取得するのに非常に優れていました。

編集

これは私が私の最後のプロジェクトでした方法です:

class BaseAuthMixin(object):
    def auth_check(self, user):
        return True

    def dispatch(self, request, *args, **kwargs):
        if not self.auth_check(request.user):
            from Django.http import HttpResponseRedirect
            from Django.contrib.auth import logout

            is_web = False
            is_live = False

            if hasattr(self, 'get_url_name'):
                from Django.core.urlresolvers import reverse
                from Django.core.urlresolvers import NoReverseMatch

                try:
                    next = reverse(self.get_url_name(), kwargs=kwargs)
                except NoReverseMatch:
                    next = ''
                else:
                    next= '?next=' + next

            logout(request)

            redirect_url = settings.LOGIN_URL
            redirect_url += next

            return HttpResponseRedirect(redirect_url)
        else:
            return super(BaseAuthMixin, self).dispatch(request, *args, **kwargs)

class LoginRequiredMixin(BaseAuthMixin):
    """
    Check if the view needs the user to be logged in.
    """
    def auth_check(self, user):
        if not super(LoginRequiredMixin, self).auth_check(user):
            return False
        else:
            if hasattr(self, 'login_required'):
                if self.login_required and not user.is_authenticated():
                    return False
        return True

class MyDefaultMixin(LoginRequiredMixin):
    """
    Mixin that inherits from all common view mixins.
    """
    pass

上記はビュークラスによって使用されます(クラスベースのビューでDjango 1.3を使用しました):

from Django.views.generic import TemplateView

class SomeViewClass(TemplateView, MyDefaultMixin):
    # Used by 'LoginRequiredMixin' to check if a user has to be logged in
    login_required = True

    # Template for the Django TemplateView
    template_name = "some_view_template.html"

ログインを処理するためのビュー(settings.LOGIN_URLのURLを使用)が必要です。このビューには、nextという非表示フィールドを持つフォームが含まれています。このフィールドは、ログインに成功した後に移動するページにコンテキスト変数で設定する必要があります。

すべてのビューがベースミックスイン(上記のコードではMyDefaultMixin)を継承している場合、ビューにlogin_requiredという属性が含まれ、それがTrueに設定されている場合、ユーザーがログインしていることを自動的に確認します。

これを行うにはもっと良い方法があるかもしれませんが、これは私がしたことであり、非常にうまく機能しました。

ミドルウェア をご覧ください。これらは、リクエストサイクルのさまざまなポイントで実行される関数です。各ビューが呼び出される前。

これから特定のビューを除外したい場合があるので、たとえばcsrfミドルウェアがどのように機能するかとcsrf_exemptデコレータ。

見る [SOURCE]/Django/views/decorators/csrf.pyおよび[SOURCE]/Django/middleware/csrf.py

3
second