我写了一个装饰器来包装我的很多观点。它基本上检查request.user是否是对象的“所有者”。
# urls.py
...
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.my_view, name='my_view'),
]
# decorators.py
...
def user_can_access_object(function):
def wrap(request, *args, **kwargs):
my_object = get_object_or_404(MyModel, pk=kwargs['pk'])
if request.user == my_object.owner:
# I actually do more to ensure the user can access, but this is for my SO question to keep it simple.
kwargs['my_object'] = my_object # <-- Am I doing something terrible here?
return function(request, *args, **kwargs)
else:
raise PermissionDenied
wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__
return wrap
# views.py
...
@login_required
@user_can_access_object
def my_view(request, pk, my_object): # Now that 'my_object' is set, my_view must be setup to accept it. Also, 'pk' is the pk for my_object.
""""
A view that does something to 'my_object'.
"""
...
some_function(my_object)
...
return render(request, "my_template.html", some_context)
这是我最初的解决方案。
# decorators.py
...
def user_can_access_object(function):
def wrap(request, *args, **kwargs):
my_object = get_object_or_404(MyModel, pk=kwargs['pk'])
if request.user == my_object.owner:
return function(request, *args, **kwargs)
else:
raise PermissionDenied
wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__
return wrap
# views.py
...
@login_required
@user_can_access_object
def my_view(request, pk): # This seems to be better, or at least more clear, It seems like the decorator is playing nicely and not modifying the request kwargs.
""""
A view that does something to 'my_object'.
"""
my_object = MyModel.objects.get(pk=pk) # My concern is that 'my_object' is looked up twice. And that seems gross and isn't this an extra database query?
...
some_function(my_object)
return render(request, "my_template.html", some_context)
我最担心的是,当my_object
添加到kwargs时,它基本上会使装饰器上的视图依赖。这似乎是不好的做法,但也许不是。