[PYTHON] 장고의 login_required를 만드는 가장 좋은 방법은 기본값입니다.
PYTHON장고의 login_required를 만드는 가장 좋은 방법은 기본값입니다.
나는 대형 Django 응용 프로그램을 개발 중입니다. 대다수의 응용 프로그램은 액세스하기 위해 로그인해야합니다. 즉, 앱 전체에 뿌려졌습니다.
@login_required
def view(...):
괜찮아요. 우리가 사방에 그것을 추가하는 것을 잊지 않는 한 훌륭하게 작동합니다! 슬프게도 때로는 잊어 버리고 실패는 종종 끔찍하게 드러나지 않습니다. 보기로 연결되는 유일한 링크가 @login_required 페이지에 있으면 로그인하지 않고도 해당보기에 실제로 도달 할 수 있음을 알지 못할 것입니다. 그러나 나쁜 사람이 알아 차릴 수 있습니다. 이는 문제입니다.
내 생각은 시스템을 뒤집는 것이었다. @login_required를 사방에 입력하는 대신, 대신 다음과 같이 할 수 있습니다.
@public
def public_view(...):
그냥 대중을 위해. 나는 이것을 약간의 미들웨어로 구현하려했으나 제대로 작동하지 않는 것처럼 보였다. 시도한 모든 것이 우리가 사용하는 다른 미들웨어와 나쁘게 상호 작용했다고 생각합니다. 다음으로 나는 @public이 아닌 모든 것이 @login_required로 표시되었는지 확인하기 위해 URL 패턴을 가로 지르는 무언가를 써 보았습니다. 적어도 우리가 뭔가를 잊어 버리면 빠른 오류를 얻을 것입니다. 그런데 어떻게하면 @login_required가 뷰에 적용되었는지 알 수있는 방법을 찾지 못했습니다 ...
그래서, 이것을하는 올바른 방법은 무엇입니까? 도와 주셔서 감사합니다!
해결법
-
==============================
1.미들웨어가 최선의 방법 일 수 있습니다. 과거에이 코드를 사용했고, 다른 곳에서 발견 된 스 니펫에서 수정했습니다.
미들웨어가 최선의 방법 일 수 있습니다. 과거에이 코드를 사용했고, 다른 곳에서 발견 된 스 니펫에서 수정했습니다.
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 데코레이터로 코드베이스를 버려야 할 필요성을 없애는 것 외에도이 접근 방식에 대해 좋아하는 점은 인증 스키마가 변경되면 전역 변경을 수행 할 수있는 한 곳이 있다는 것입니다.
-
==============================
2.각보기 기능에 데코레이터를 배치하는 대신에 다른 방법이 있습니다. urls.py 파일에 login_required () 데코레이터를 넣을 수도 있습니다. 이 작업은 여전히 수동 작업이지만 적어도 한 곳에서 모든 작업을 수행 할 수 있으므로 감사가 쉬워집니다.
각보기 기능에 데코레이터를 배치하는 대신에 다른 방법이 있습니다. 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)), )
뷰 함수는 문자열이 아니라 직접 이름이 지정되고 가져 오기됩니다.
또한이 클래스는 클래스를 포함하여 호출 가능한 뷰 객체와 함께 작동합니다.
-
==============================
3.URL을 함수를보기 위해 전달하는 방식을 변경하지 않고 Django에 내장 된 가정을 변경하는 것은 어렵습니다.
URL을 함수를보기 위해 전달하는 방식을 변경하지 않고 Django에 내장 된 가정을 변경하는 것은 어렵습니다.
Django 내부에서의 작업 대신, 사용할 수있는 감사가 있습니다. 각보기 기능을 확인하기 만하면됩니다.
import os import re def view_modules( root ): for path, dirs, files in os.walk( root ): for d in dirs[:]: if d.startswith("."): dirs.remove(d) for f in files: name, ext = os.path.splitext(f) if ext == ".py": if name == "views": yield os.path.join( path, f ) def def_lines( root ): def_pat= re.compile( "\n(\S.*)\n+(^def\s+.*:$)", re.MULTILINE ) for v in view_modules( root ): with open(v,"r") as source: text= source.read() for p in def_pat.findall( text ): yield p def report( root ): for decorator, definition in def_lines( root ): print decorator, definition
이것을 실행하고 적절한 데코레이터없이 def의 출력을 검사하십시오.
-
==============================
4.Ber의 대답에서 영감을 얻은 필자는 모든 콜백을 login_required 데코레이터로 래핑하여 패턴 함수를 대신하는 간단한 스 니펫을 작성했습니다. 이것은 장고 1.6에서 작동합니다.
Ber의 대답에서 영감을 얻은 필자는 모든 콜백을 login_required 데코레이터로 래핑하여 패턴 함수를 대신하는 간단한 스 니펫을 작성했습니다. 이것은 장고 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
그것을 사용하면 다음과 같이 작동합니다 (수확량 때문에 목록에 대한 호출이 필요합니다).
urlpatterns = list(login_required_patterns('', url(r'^$', home_view)))
-
==============================
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
LOGIN_REQUIRED_URLS = ( r'(.*)', ) LOGIN_REQUIRED_URLS_EXCEPTIONS = ( r'/admin(.*)$', ) LOGIN_URL = '/admin'
-
==============================
6.너는 이길 수 없다. 인증 요구 사항을 선언하기 만하면됩니다. 뷰 기능을 제외하고는이 선언을 어디에 둘 것인가?
너는 이길 수 없다. 인증 요구 사항을 선언하기 만하면됩니다. 뷰 기능을 제외하고는이 선언을 어디에 둘 것인가?
보기 기능을 호출 대상으로 대체하는 것이 좋습니다.
class LoginViewFunction( object ): def __call__( self, request, *args, **kw ): p1 = self.login( request, *args, **kw ) if p1 is not None: return p1 return self.view( request, *args, **kw ) def login( self, request ) if not request.user.is_authenticated(): return HttpResponseRedirect('/login/?next=%s' % request.path) def view( self, request, *args, **kw ): raise NotImplementedError
그런 다음 LoginViewFunction의 뷰 기능 서브 클래스를 작성하십시오.
class MyRealView( LoginViewFunction ): def view( self, request, *args, **kw ): .... the real work ... my_real_view = MyRealView()
코드 줄을 저장하지 않습니다. 그리고 그것은 "우리가 잊은"문제를 돕지 않습니다. 당신이 할 수있는 일은 코드를 검사하여 뷰 기능이 객체인지 확인하는 것입니다. 올바른 반에서.
그러나 그때조차도 모든 뷰 기능이 단위 테스트 스위트 없이는 정확하다는 것을 결코 알 수 없을 것입니다.
-
==============================
7.include의 일종으로 모든 URL에 대한 단일 시작 지점을 가질 수 있으며이 패키지 https://github.com/vorujack/decorate_url을 사용하여 꾸미십시오.
include의 일종으로 모든 URL에 대한 단일 시작 지점을 가질 수 있으며이 패키지 https://github.com/vorujack/decorate_url을 사용하여 꾸미십시오.
-
==============================
8.Django 2.1에서는 클래스의 모든 메소드를 다음과 같이 꾸밀 수 있습니다.
Django 2.1에서는 클래스의 모든 메소드를 다음과 같이 꾸밀 수 있습니다.
from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import TemplateView @method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html'
from https://stackoverflow.com/questions/2164069/best-way-to-make-djangos-login-required-the-default by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 사람이 읽을 수있는 버전의 파일을 재사용 할 수있는 라이브러리? (0) | 2018.10.16 |
---|---|
[PYTHON] 명령 줄 인수를 구문 분석하는 가장 좋은 방법은 무엇입니까? (0) | 2018.10.16 |
[PYTHON] 어떻게 여러 제출 버튼 장고 양식을 만들 수 있습니까? (0) | 2018.10.16 |
[PYTHON] virtualenv에 환경 변수 설정하기 (0) | 2018.10.16 |
[PYTHON] 포스트그레스 : 이미 존재하지 않는 INSERT (0) | 2018.10.16 |