Python 是不是;好",;让我的视图装饰器向传递给视图函数的kwargs添加一个项?

Python 是不是;好",;让我的视图装饰器向传递给视图函数的kwargs添加一个项?,python,django,django-views,python-decorators,Python,Django,Django Views,Python Decorators,我写了一封装饰信,用它来包装我的许多观点。它主要检查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):

我写了一封装饰信,用它来包装我的许多观点。它主要检查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)

我最担心的是,当
My_object
添加到kwargs时,它基本上会使视图依赖于装饰器。这似乎是一种不好的做法,但可能并非如此。

请注意,由于其作用域
my_对象
在您的视图中仍然可用。您可能希望在这里使用自定义
dispatch()
方法的基于类的视图。按照上面的注释,您可以执行类似操作,而不是更改
kwargs
,例如:
尝试:my\u对象,但名称错误除外:my\u对象=MyModel.objects.get(pk=pk)
。然后视图就不再依赖于装饰器了。有时候在这个用例中,更有趣的是在测试用户权限之前,不显示用户不允许跟随的链接。
# 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)