Osc*_*lal 151 django django-views django-authentication django-class-based-views class-based-views
我在理解新CBV如何工作方面遇到了一些麻烦.我的问题是,我需要登录所有视图,其中一些是特定权限.在基于函数的视图中,我使用@permission_required()和视图中的login_required属性执行此操作,但我不知道如何在新视图上执行此操作.django文档中是否有一些部分解释了这一点?我没找到任何东西.我的代码有什么问题?
我尝试使用@method_decorator,但它回复" / errors/prueba/_wrapped_view()中的TypeError至少需要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
Run Code Online (Sandbox Code Playgroud)
A L*_*Lee 188
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'
Run Code Online (Sandbox Code Playgroud)
在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)
Run Code Online (Sandbox Code Playgroud)使用Django 1.9+中提供的django.contrib.auth.mixins.LoginRequiredMixin等访问mixins ,并在其他答案中概述:
from django.contrib.auth.mixins import LoginRequiredMixin
class MyView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
Run Code Online (Sandbox Code Playgroud)你得到的原因TypeError在文档中解释:
注意:method_decorator将*args和**kwargs作为参数传递给类上的装饰方法.如果您的方法不接受兼容的参数集,则会引发TypeError异常.
Ger*_*eyn 115
这是我的方法,我创建一个受保护的mixin(这保存在我的mixin库中):
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)
Run Code Online (Sandbox Code Playgroud)
每当您想要保护视图时,只需添加适当的mixin:
class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
template_name = 'index.html'
Run Code Online (Sandbox Code Playgroud)
只要确保你的mixin是第一个.
更新:我在2011年发布了这个版本,从版本1.9开始Django现在包括这个和其他有用的mixin(AccessMixin,PermissionRequiredMixin,UserPassesTestMixin)作为标准!
mjt*_*lyn 45
这是使用基于类的装饰器的替代方法:
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
Run Code Online (Sandbox Code Playgroud)
然后可以像这样简单地使用它:
@class_view_decorator(login_required)
class MyView(View):
# this view now decorated
Run Code Online (Sandbox Code Playgroud)
mep*_*sto 14
我意识到这个线程有点陈旧,但无论如何这里是我的两分钱.
使用以下代码:
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
Run Code Online (Sandbox Code Playgroud)
我们现在有办法修补装饰器,因此它将变得多功能化.这实际上意味着当应用于常规视图装饰器时,如下所示:
login_required = patch_view_decorator(login_required)
Run Code Online (Sandbox Code Playgroud)
这个装饰器在按原来的方式使用时仍然可以工作:
@login_required
def foo(request):
return HttpResponse('bar')
Run Code Online (Sandbox Code Playgroud)
但在使用时也会正常工作:
@login_required
class FooView(DetailView):
model = Foo
Run Code Online (Sandbox Code Playgroud)
在我最近遇到的几个案例中,这似乎工作得很好,包括这个现实世界的例子:
@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
Run Code Online (Sandbox Code Playgroud)
编写ajax_view函数是为了修改(基于函数的)视图,因此每当非ajax调用访问此视图时,它都会引发404错误.通过简单地将补丁函数应用为装饰器,该装饰器也被设置为在基于类的视图中工作
vis*_*ell 14
对于那些你谁使用的Django> = 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'
Run Code Online (Sandbox Code Playgroud)
这也很好地记住GCBV密新秩序:混入必须走在左边一侧,基本视图类必须在走右边侧.如果订单不同,您可能会破坏不可预测的结果.
小智 5
使用 Django 大括号。它提供了许多易于使用的有用的mixin。它有漂亮的文档。试试看。
您甚至可以创建自定义的 mixin。
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({})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
79792 次 |
| 最近记录: |