python - 필터 - 템플릿 언어란




장고의 login_required를 만드는 가장 좋은 방법은 기본값입니다. (5)

여기에 장고를위한 미들웨어 솔루션입니다 1.10 +

미들웨어는 장고 1.10+에서 새로운 방식으로 작성되어야합니다 .

암호

import re

from django.conf import settings
from django.contrib.auth.decorators import login_required


class RequireLoginMiddleware(object):

    def __init__(self, get_response):
         # One-time configuration and initialization.
        self.get_response = get_response

        self.required = tuple(re.compile(url)
                              for url in settings.LOGIN_REQUIRED_URLS)
        self.exceptions = tuple(re.compile(url)
                                for url in settings.LOGIN_REQUIRED_URLS_EXCEPTIONS)

    def __call__(self, request):

        response = self.get_response(request)
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):

        # No need to process URLs if user already logged in
        if request.user.is_authenticated:
            return None

        # An exception match should immediately return None
        for url in self.exceptions:
            if url.match(request.path):
                return None

        # Requests matching a restricted URL pattern are returned
        # wrapped with the login_required decorator
        for url in self.required:
            if url.match(request.path):
                return login_required(view_func)(request, *view_args, **view_kwargs)

        # Explicitly return None for all non-matching requests
        return None

설치

  1. 코드를 프로젝트 폴더에 복사하고 middleware.py로 저장하십시오.
  2. 미들웨어에 추가

    MIDDLEWARE = ​​[... '.middleware.RequireLoginMiddleware', # 로그인 필요]

  3. 귀하의 settings.py에 추가하십시오 :
LOGIN_REQUIRED_URLS = (
    r'(.*)',
)
LOGIN_REQUIRED_URLS_EXCEPTIONS = (
    r'/admin(.*)$',
)
LOGIN_URL = '/admin'

출처 :

  1. Daniel Naab의 답입니다.

  2. 맥스 굿지 (Max Goodridge) 장고 미들웨어 자습서

  3. 장고 미들웨어 문서

나는 대형 Django 응용 프로그램을 개발 중입니다. 대다수의 응용 프로그램은 로그인을 위해 액세스해야합니다. 즉, 앱 전체에 뿌려졌습니다.

@login_required
def view(...):

괜찮아요. 우리가 사방에 그것을 추가하는 것을 잊지 않는 한 훌륭하게 작동합니다! 슬프게도 때로는 잊어 버리고 실패는 종종 끔찍하게 드러나지 않습니다. 보기로 연결되는 유일한 링크가 @login_required 페이지에 있으면 로그인하지 않고도 해당보기에 실제로 도달 할 수 있음을 알지 못할 것입니다. 그러나 나쁜 사람이 알아 차릴 수 있습니다. 이는 문제입니다.

내 생각은 시스템을 뒤집는 것이었다. @login_required를 사방에 입력하는 대신, 대신 다음과 같이 할 수 있습니다.

@public
def public_view(...):

그냥 대중을 위해. 나는 이것을 약간의 미들웨어로 구현하려했으나 제대로 작동하지 않는 것처럼 보였다. 시도한 모든 것이 우리가 사용하는 다른 미들웨어와 나쁘게 상호 작용했다고 생각합니다. 다음으로 나는 @public이 아닌 모든 것이 @login_required로 표시되었는지 확인하기 위해 URL 패턴을 가로 지르는 무언가를 써 보았습니다. 적어도 우리가 뭔가를 잊어 버리면 빠른 오류를 얻을 것입니다. 그런데 어떻게하면 @login_required가 뷰에 적용되었는지 알 수있는 방법을 찾지 못했습니다 ...

그래서, 이것을하는 올바른 방법은 무엇입니까? 도와 주셔서 감사합니다!


Ber의 대답에서 영감을 얻은 필자는 모든 콜백을 login_required 데코레이터로 래핑하여 patterns 함수를 대신하는 간단한 스 니펫을 작성했습니다. 이것은 장고 1.6에서 작동합니다.

def login_required_patterns(*args, **kw):
    for pattern in patterns(*args, **kw):
        # This is a property that should return a callable, even if a string view name is given.
        callback = pattern.callback

        # No property setter is provided, so this will have to do.
        pattern._callback = login_required(callback)

        yield pattern

그것을 사용하면 다음과 같이 작동합니다 ( yield 때문에 list 대한 호출이 필요합니다).

urlpatterns = list(login_required_patterns('', url(r'^$', home_view)))


각보기 기능에 데코레이터를 배치하는 대신에 다른 방법이 있습니다. urls.py 파일에 login_required() 데코레이터를 넣을 수도 있습니다. 이 작업은 여전히 ​​수동 작업이지만 적어도 한 곳에서 모든 작업을 수행 할 수 있으므로 감사가 쉬워집니다.

예를 들어,

    from my_views import home_view

    urlpatterns = patterns('',
        # "Home":
        (r'^$', login_required(home_view), dict(template_name='my_site/home.html', items_per_page=20)),
    )

뷰 함수는 문자열이 아니라 직접 이름이 지정되고 가져 오기됩니다.

또한이 클래스는 클래스를 포함하여 호출 가능한 뷰 객체와 함께 작동합니다.


미들웨어가 최선의 방법 일 수 있습니다. 과거에이 코드를 사용했고, 다른 곳에서 발견 된 스 니펫에서 수정했습니다.

import re

from django.conf import settings
from django.contrib.auth.decorators import login_required


class RequireLoginMiddleware(object):
    """
    Middleware component that wraps the login_required decorator around
    matching URL patterns. To use, add the class to MIDDLEWARE_CLASSES and
    define LOGIN_REQUIRED_URLS and LOGIN_REQUIRED_URLS_EXCEPTIONS in your
    settings.py. For example:
    ------
    LOGIN_REQUIRED_URLS = (
        r'/topsecret/(.*)$',
    )
    LOGIN_REQUIRED_URLS_EXCEPTIONS = (
        r'/topsecret/login(.*)$',
        r'/topsecret/logout(.*)$',
    )
    ------
    LOGIN_REQUIRED_URLS is where you define URL patterns; each pattern must
    be a valid regex.

    LOGIN_REQUIRED_URLS_EXCEPTIONS is, conversely, where you explicitly
    define any exceptions (like login and logout URLs).
    """
    def __init__(self):
        self.required = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS)
        self.exceptions = tuple(re.compile(url) for url in settings.LOGIN_REQUIRED_URLS_EXCEPTIONS)

    def process_view(self, request, view_func, view_args, view_kwargs):
        # No need to process URLs if user already logged in
        if request.user.is_authenticated():
            return None

        # An exception match should immediately return None
        for url in self.exceptions:
            if url.match(request.path):
                return None

        # Requests matching a restricted URL pattern are returned
        # wrapped with the login_required decorator
        for url in self.required:
            if url.match(request.path):
                return login_required(view_func)(request, *view_args, **view_kwargs)

        # Explicitly return None for all non-matching requests
        return None

그런 다음 settings.py에서 보호하려는 기본 URL을 나열하십시오.

LOGIN_REQUIRED_URLS = (
    r'/private_stuff/(.*)$',
    r'/login_required/(.*)$',
)

사이트가 인증이 필요한 페이지에 대한 URL 규칙을 따르는 한이 모델이 작동합니다. 이것이 일대일로 적합하지 않은 경우 미들웨어를 수정하여 상황에 더 밀접하게 맞출 수 있습니다.

@login_required 데코레이터로 코드베이스를 @login_required 할 필요성을 없애는 것 외에도이 접근 방식에 대해 좋아하는 점은 인증 스키마가 변경되면 전역 변경을 수행 할 수있는 한 곳이 있다는 것입니다.





django