我在views.py
中有一组功能,目前只有用户可以访问。我被要求公开访问,目前我在视图中使用@login_required
装饰器。有没有办法根据所服务的对象有条件地应用这个装饰器?
例如,我views.py
的一部分:
@login_required
def details(request, object_id):
o = get_object_or_404(Model, pk=object_id)
if o.user_id == request.user.pk:
return render(request, 'app/details.html')
else:
return redirect('app:home')
我想做什么:
if not o.is_public:
@login_required
def details(request, object_id):
o = get_object_or_404(Model, pk=object_id)
if o.user_id == request.user.pk:
return render(request, 'app/details.html')
else:
return redirect('app:home')
当然,代码不起作用,因为(i)它不是有效的Python和(ii)我需要先得到对象。我相信使用Django可能会有一个优雅的解决方案,因为这在Web应用程序中是一个非常常见的功能,但我已经通过文档无济于事。我想我应该用另一个装饰器包围@login_required
装饰器,但我不太熟悉Python中的装饰器。任何帮助表示赞赏。
答案 0 :(得分:0)
您可以使用user_passes_test
来表达此类行为。
from django.contrib.auth.decorators import user_passes_test
def public_check(user):
if user.is_public:
return True
@user_passes_test(public_check)
答案 1 :(得分:0)
它不适用于装饰器,因为装饰器在导入时被评估并应用,正如您所说,您需要首先获取对象,这取决于请求。
由于您已经要求一个优雅的解决方案,并且我假设您想为它创建一个装饰器,以便您可以在多个视图上重复使用它,那么解决方案就是基于类的视图。您可以将您想要的行为实现为基于类的视图mixin,您可以将其混合到不同的基于类的视图中。这种改进的灵活性是引入基于类的视图的原因之一。