장고 클래스 기반 뷰에서 permission_required 데코레이터를 사용하는 방법
새 CBV의 작동 방식을 이해하는 데 약간의 어려움이 있습니다. 내 질문은 이것입니다. 모든보기와 특정 권한에 로그인해야합니다. 함수 기반 뷰에서는 뷰의 @permission_required () 및 login_required 속성을 사용하여 수행하지만 새 뷰 에서이 작업을 수행하는 방법을 모르겠습니다. 장고 문서에 이것을 설명하는 섹션이 있습니까? 아무것도 찾지 못했습니다. 내 코드에 어떤 문제가 있습니까?
@method_decorator를 사용하려고했지만 " / spaces / prueba /의 TypeError _wrapped_view ()에서 1 개 이상의 인수 (0)가 발생했습니다. "
다음은 코드 (GPL)입니다.
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required, permission_required
class ViewSpaceIndex(DetailView):
"""
Show the index page of a space. Get various extra contexts to get the
information for that space.
The get_object method searches in the user 'spaces' field if the current
space is allowed, if not, he is redirected to a 'nor allowed' page.
"""
context_object_name = 'get_place'
template_name = 'spaces/space_index.html'
@method_decorator(login_required)
def get_object(self):
space_name = self.kwargs['space_name']
for i in self.request.user.profile.spaces.all():
if i.url == space_name:
return get_object_or_404(Space, url = space_name)
self.template_name = 'not_allowed.html'
return get_object_or_404(Space, url = space_name)
# Get extra context data
def get_context_data(self, **kwargs):
context = super(ViewSpaceIndex, self).get_context_data(**kwargs)
place = get_object_or_404(Space, url=self.kwargs['space_name'])
context['entities'] = Entity.objects.filter(space=place.id)
context['documents'] = Document.objects.filter(space=place.id)
context['proposals'] = Proposal.objects.filter(space=place.id).order_by('-pub_date')
context['publication'] = Post.objects.filter(post_space=place.id).order_by('-post_pubdate')
return context
CBV 문서 에는 다음과 같은 몇 가지 전략이 있습니다 .
urls.py
경로에 데코레이터를 추가하십시오 ( 예 :login_required(ViewSpaceIndex.as_view(..))
dispatch
method_decorator
예를 들어 CBV의 방법을 장식하십시오 .from django.utils.decorators import method_decorator @method_decorator(login_required, name='dispatch') class ViewSpaceIndex(TemplateView): template_name = 'secret.html'
Django 1.9 이전
method_decorator
에는 클래스에서 사용할 수 없으므로dispatch
메소드 를 재정의해야 합니다.class ViewSpaceIndex(TemplateView): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)
Django 1.9 이상에서 제공되는 django.contrib.auth.mixins.LoginRequiredMixin 과 같은 액세스 믹스 인을 사용하고 다른 답변에 잘 설명되어 있습니다.
from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): login_url = '/login/' redirect_field_name = 'redirect_to'
당신이 얻는 이유 TypeError
는 문서에 설명되어 있습니다 :
참고 : method_decorator는 * args 및 ** kwargs를 매개 변수로 클래스의 데코 레이팅 된 메소드에 전달합니다. 메소드가 호환 가능한 매개 변수 세트를 승인하지 않으면 TypeError 예외가 발생합니다.
여기 내 접근 방식이 있습니다, 나는 보호되는 믹스 인을 만듭니다 (이것은 내 믹스 인 라이브러리에 보관되어 있습니다).
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class LoginRequiredMixin(object):
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
보기를 보호 할 때마다 적절한 믹스 인을 추가하십시오.
class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
template_name = 'index.html'
믹스 인이 먼저 있는지 확인하십시오.
업데이트 : 2011 년 1.9부터 시작 하여이 방법을 게시했습니다 .Django는 이제 이것과 다른 유용한 믹스 인 (AccessMixin, PermissionRequiredMixin, UserPassesTestMixin)을 표준으로 포함합니다!
클래스 기반 데코레이터를 사용하는 대안은 다음과 같습니다.
from django.utils.decorators import method_decorator
def class_view_decorator(function_decorator):
"""Convert a function based decorator into a class based decorator usable
on class based Views.
Can't subclass the `View` as it breaks inheritance (super in particular),
so we monkey-patch instead.
"""
def simple_decorator(View):
View.dispatch = method_decorator(function_decorator)(View.dispatch)
return View
return simple_decorator
그러면 다음과 같이 간단하게 사용할 수 있습니다.
@class_view_decorator(login_required)
class MyView(View):
# this view now decorated
나는이 스레드가 약간 오래되었다는 것을 알고 있지만 어쨌든 내 2 센트가 있습니다.
다음 코드로 :
from django.utils.decorators import method_decorator
from inspect import isfunction
class _cbv_decorate(object):
def __init__(self, dec):
self.dec = method_decorator(dec)
def __call__(self, obj):
obj.dispatch = self.dec(obj.dispatch)
return obj
def patch_view_decorator(dec):
def _conditional(view):
if isfunction(view):
return dec(view)
return _cbv_decorate(dec)(view)
return _conditional
이제 데코레이터를 패치 할 수있는 방법이 생겨서 다기능이 될 것입니다. 이것은 다음과 같이 일반 뷰 데코레이터에 적용될 때 효과적으로 의미합니다.
login_required = patch_view_decorator(login_required)
이 데코레이터는 원래 의도 된 방식으로 사용될 때 여전히 작동합니다.
@login_required
def foo(request):
return HttpResponse('bar')
그러나 다음과 같이 사용하면 올바르게 작동합니다.
@login_required
class FooView(DetailView):
model = Foo
이것은 실제 사례를 포함하여 최근에 접한 몇 가지 경우에 잘 작동하는 것 같습니다.
@patch_view_decorator
def ajax_view(view):
def _inner(request, *args, **kwargs):
if request.is_ajax():
return view(request, *args, **kwargs)
else:
raise Http404
return _inner
ajax_view 함수는 (함수 기반)보기를 수정하기 위해 작성되므로,이보기가 ajax가 아닌 호출에 의해 방문 될 때마다 404 오류가 발생합니다. 단순히 데코레이터로 패치 기능을 적용함으로써이 데코레이터는 모두 클래스 기반 뷰에서도 작동하도록 설정됩니다
사용하는 분들을 위해 > = 1.9 장고를 , 그것은 이미에 포함 django.contrib.auth.mixins
으로 AccessMixin
, LoginRequiredMixin
, PermissionRequiredMixin
와 UserPassesTestMixin
.
따라서 LoginRequired를 CBV (예 :)에 적용하려면 다음을 수행하십시오 DetailView
.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import DetailView
class ViewSpaceIndex(LoginRequiredMixin, DetailView):
model = Space
template_name = 'spaces/space_index.html'
login_url = '/login/'
redirect_field_name = 'redirect_to'
그것은 마음 GCBV 믹스 인 순서로 유지하는 것이 좋다 : 유지 mixin은 온 가야 왼쪽 측면 및 기본 뷰 클래스에 가야 바로 옆. 순서가 다르면 깨지거나 예측할 수없는 결과를 얻을 수 있습니다.
Django Braces를 사용하십시오. 쉽게 사용할 수있는 많은 유용한 믹스 인을 제공합니다. 아름다운 문서가 있습니다. 사용해보십시오.
커스텀 믹스 인을 만들 수도 있습니다.
http://django-braces.readthedocs.org/en/v1.4.0/
예제 코드 :
from django.views.generic import TemplateView
from braces.views import LoginRequiredMixin
class SomeSecretView(LoginRequiredMixin, TemplateView):
template_name = "path/to/template.html"
#optional
login_url = "/signup/"
redirect_field_name = "hollaback"
raise_exception = True
def get(self, request):
return self.render_to_response({})
대부분의 페이지에서 사용자가 로그인해야하는 사이트 인 경우 미들웨어를 사용하여 특별히 표시된 일부를 제외한 모든보기에서 강제로 로그인 할 수 있습니다 .
Pre Django 1.10 middleware.py :
from django.contrib.auth.decorators import login_required
from django.conf import settings
EXEMPT_URL_PREFIXES = getattr(settings, 'LOGIN_EXEMPT_URL_PREFIXES', ())
class LoginRequiredMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
path = request.path
for exempt_url_prefix in EXEMPT_URL_PREFIXES:
if path.startswith(exempt_url_prefix):
return None
is_login_required = getattr(view_func, 'login_required', True)
if not is_login_required:
return None
return login_required(view_func)(request, *view_args, **view_kwargs)
views.py :
def public(request, *args, **kwargs):
...
public.login_required = False
class PublicView(View):
...
public_view = PublicView.as_view()
public_view.login_required = False
래핑하지 않으려는 타사보기는 설정에서 제외 할 수 있습니다.
settings.py :
LOGIN_EXEMPT_URL_PREFIXES = ('/login/', '/reset_password/')
In my code I have written this adapter to adapt member functions to a non-member function:
from functools import wraps
def method_decorator_adaptor(adapt_to, *decorator_args, **decorator_kwargs):
def decorator_outer(func):
@wraps(func)
def decorator(self, *args, **kwargs):
@adapt_to(*decorator_args, **decorator_kwargs)
def adaptor(*args, **kwargs):
return func(self, *args, **kwargs)
return adaptor(*args, **kwargs)
return decorator
return decorator_outer
You can simply use it like this:
from django.http import HttpResponse
from django.views.generic import View
from django.contrib.auth.decorators import permission_required
from some.where import method_decorator_adaptor
class MyView(View):
@method_decorator_adaptor(permission_required, 'someapp.somepermission')
def get(self, request):
# <view logic>
return HttpResponse('result')
This is super easy with django > 1.9 coming with support for PermissionRequiredMixin
and LoginRequiredMixin
Just import from the auth
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
class YourListView(LoginRequiredMixin, Views):
pass
For more details read Authorization in django
If you are doing a project which requires variety of permission tests, you can inherit this class.
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from django.views.generic import View
from django.utils.decorators import method_decorator
class UserPassesTest(View):
'''
Abstract base class for all views which require permission check.
'''
requires_login = True
requires_superuser = False
login_url = '/login/'
permission_checker = None
# Pass your custom decorator to the 'permission_checker'
# If you have a custom permission test
@method_decorator(self.get_permission())
def dispatch(self, *args, **kwargs):
return super(UserPassesTest, self).dispatch(*args, **kwargs)
def get_permission(self):
'''
Returns the decorator for permission check
'''
if self.permission_checker:
return self.permission_checker
if requires_superuser and not self.requires_login:
raise RuntimeError((
'You have assigned requires_login as False'
'and requires_superuser as True.'
" Don't do that!"
))
elif requires_login and not requires_superuser:
return login_required(login_url=self.login_url)
elif requires_superuser:
return user_passes_test(lambda u:u.is_superuser,
login_url=self.login_url)
else:
return user_passes_test(lambda u:True)
I've made that fix based on Josh's solution
class LoginRequiredMixin(object):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
Sample usage:
class EventsListView(LoginRequiredMixin, ListView):
template_name = "events/list_events.html"
model = Event
It has been a while now and now Django has changed so much.
Check here for how to decorate a class-based view.
https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/#decorating-the-class
The documentation did not include an example of "decorators that takes any argument". But decorators that take arguments are like this:
def mydec(arg1):
def decorator(func):
def decorated(*args, **kwargs):
return func(*args, **kwargs) + arg1
return decorated
return deocrator
so if we are to use mydec as a "normal" decorator without arguments, we can do this:
mydecorator = mydec(10)
@mydecorator
def myfunc():
return 5
So similarly, to use permission_required
with method_decorator
we can do:
@method_decorator(permission_required("polls.can_vote"), name="dispatch")
class MyView:
def get(self, request):
# ...
'Programing' 카테고리의 다른 글
.Net 어셈블리의 PublicKeyToken 얻기 (0) | 2020.06.10 |
---|---|
저자를 변경하기 위해 Git에서 여러 커밋을 수정하는 방법 (0) | 2020.06.10 |
ASP.NET MVC에서 View Model을 JSON 객체로 변환하는 방법은 무엇입니까? (0) | 2020.06.10 |
Guzzle 6 : 응답을위한 더 이상 json () 메소드 (0) | 2020.06.10 |
프로그래밍 방식으로 축소 또는 축소 축소 도구 모음 레이아웃 (0) | 2020.06.10 |