使用中间件为django中的视图函数添加参数
Using middleware to add arguments to view functions in django
我有一个非常小的基本站点,只有少量视图。几乎所有的视图都与外部 API.
进行了一些交互
在每个视图中,我都实例化了我的 API class 的一个对象,这显然不是很 DRY。我还有一个中间件,可以向请求对象添加一个或两个有用的变量(我的中间件在链中最后运行)。
我想在中间件中实例化我的 api class,然后将其作为参数传递给每个视图,即
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
这似乎是一种快速简便的整理代码和减少重复的方法。这有什么本质上不好的地方吗?
您可以使用中间件,但还有其他两种可能性,两者都更灵活。第一个是使用装饰器并包装视图:
@my_api_init_decorator
def my_view(request, my_api):
...
这允许您在初始化 api...
之前显式 select 查看、检查用户授权或权限
第二种解决方案是使用基于 class 的视图并创建您自己的继承视图。
如果您查看 Django 中间件 documentation,您会看到;
If process_view returns an HttpResponse object, Django won’t bother calling any other view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.
因此返回一个 HttpResponse 将跳过其他中间件 类 在这个中间件下面的执行 通常应该避免 除非你的中间件是 settings.MIDDLEWARE_CLASSES 列表.
但是,您仍然可以将 API 对象绑定到传递给中间件的 HttpRequest 实例。这与 AuhenticationMiddleware 填充 request.user.
的方法相同
def APIMiddleware(object):
def process_request(self, request):
request.api = API(host, port, user, password, extra={"url": request.get_full_path()})
你可以在中间件
中更改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
中间件 returns None,Django 将继续处理此请求,执行任何其他 process_view() 中间件。
但是,这只适用于每个视图函数都可以得到关键字参数'myapi',否则会引发 TypeError。
所以最好的方法不是通过 func 参数传递你的 api,就像@ozgur 通过请求传递你的 api。
我有一个非常小的基本站点,只有少量视图。几乎所有的视图都与外部 API.
进行了一些交互在每个视图中,我都实例化了我的 API class 的一个对象,这显然不是很 DRY。我还有一个中间件,可以向请求对象添加一个或两个有用的变量(我的中间件在链中最后运行)。
我想在中间件中实例化我的 api class,然后将其作为参数传递给每个视图,即
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
这似乎是一种快速简便的整理代码和减少重复的方法。这有什么本质上不好的地方吗?
您可以使用中间件,但还有其他两种可能性,两者都更灵活。第一个是使用装饰器并包装视图:
@my_api_init_decorator
def my_view(request, my_api):
...
这允许您在初始化 api...
之前显式 select 查看、检查用户授权或权限第二种解决方案是使用基于 class 的视图并创建您自己的继承视图。
如果您查看 Django 中间件 documentation,您会看到;
If process_view returns an HttpResponse object, Django won’t bother calling any other view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.
因此返回一个 HttpResponse 将跳过其他中间件 类 在这个中间件下面的执行 通常应该避免 除非你的中间件是 settings.MIDDLEWARE_CLASSES 列表.
但是,您仍然可以将 API 对象绑定到传递给中间件的 HttpRequest 实例。这与 AuhenticationMiddleware 填充 request.user.
的方法相同def APIMiddleware(object):
def process_request(self, request):
request.api = API(host, port, user, password, extra={"url": request.get_full_path()})
你可以在中间件
中更改view_kwargsclass 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 中间件 returns None,Django 将继续处理此请求,执行任何其他 process_view() 中间件。
但是,这只适用于每个视图函数都可以得到关键字参数'myapi',否则会引发 TypeError。
所以最好的方法不是通过 func 参数传递你的 api,就像@ozgur 通过请求传递你的 api。