使用中间件添加参数以查看 django 中的函数

Posted

技术标签:

【中文标题】使用中间件添加参数以查看 django 中的函数【英文标题】:Using middleware to add arguments to view functions in django 【发布时间】:2015-02-04 19:39:52 【问题描述】:

我有一个很小的基本网站,但浏览量很少。几乎所有视图都与外部 API 进行一些交互。

在每个视图中,我都实例化了我的 API 类的一个对象,这显然不是很干。我还有一个中间件,它向请求对象添加一个或两个有用的变量(我的中间件在链中最后运行)。

我正在考虑在中间件中实例化我的 api 类,然后将其作为参数传递给每个视图,即

def my_view(request, my_api_class_instance):

然后从中间件调用视图,类似于:

def process_view(self, request, view_func, view_args, view_kwargs):
    my_api = api(some, args, here)
    response = view_func(request, my_api, *view_args, **view_kwargs)
    return response

这似乎是一种整理代码和减少重复的快速简便的方法。这有什么不好的地方吗?

【问题讨论】:

【参考方案1】:

如果你查看 Django 中间件documentation,你会看到;

如果 process_view 返回一个 HttpResponse 对象,Django 不会费心调用任何其他视图或异常中间件,或适当的视图;它将响应中间件应用于该 HttpResponse,并返回结果。

因此,返回 HttpResponse 将跳过执行低于该中间件的其他中间件类,一般应避免,除非您的中间件是 settings.MIDDLEWARE_CLASSES 列表中的最后一个.

但是,您仍然可以将 API 对象绑定到传递给中间件的 HttpRequest 实例。这与 AuthenticationMiddleware 为填充 request.user 所做的方法相同。

def APIMiddleware(object):
    def process_request(self, request):
        request.api = API(host, port, user, password, extra="url": request.get_full_path())

【讨论】:

【参考方案2】:

您可以在中间件中更改 view_kwargs

class SomeMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        view_kwargs['my_api'] = api(some, args, here)
        return None

def my_view(request, my_api):
    # you can use you api there
def my_view(request, args, my_api)
    # you can use you api there

document it's there 中间件返回 None,Django 将继续处理这个请求,执行任何其他 process_view() 中间件。

但是,这只适用于每个视图函数都可以得到关键字参数'myapi',否则会引发TypeError。

所以最好的方法不是通过 func 参数传递你的 api,比如 @ozgur 通过请求传递你的 api。

【讨论】:

【参考方案3】:

您可以使用中间件,但也有其他两种可能性,都更灵活。第一种是使用装饰器并包装视图:

@my_api_init_decorator
def my_view(request, my_api):
    ...

这允许您在初始化 api 之前显式选择视图、检查用户授权或权限...

第二种解决方案是使用基于类的视图并创建您自己的继承视图。

【讨论】:

这样,开发人员最终可能不得不用一个新的装饰器来包装应用程序中的所有视图,这既不灵活也不通用。 取决于您的用例。如果所有视图都需要 api 访问并且它永远不会改变,那么使用中间件。如果存在/将有不需要 api 访问的视图,那么最好使用其中一种可能性。它的方式很灵活,您可以非常轻松地控制哪个视图具有 api 访问权限,哪个视图没有。或者,您可以在 api 初始化之前检查每个视图的权限(其他事情)(当 api init 是一个昂贵的调用并且您希望最小化这些调用时很有用)。 问题是:“几乎所有的视图都与外部 API 进行一些交互。”,所以中间件应该是首选方法。

以上是关于使用中间件添加参数以查看 django 中的函数的主要内容,如果未能解决你的问题,请参考以下文章

django之中间件设置

django基础知识之中间件:

Django:向视图中的请求添加可选参数

Django:如何访问中间件类中的 URL 正则表达式参数?

Django之中间件与form其他用法

[django]中间件