您好我正在审核Werkzeug tutorial,我对此声明感到有些困惑:app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/static': os.path.join(os.path.dirname(__file__), 'static')
})
包含在内部:
class Shortly(object):
def __init__(self, config):
self.redis = redis.Redis(config['redis_host'], config['redis_port'])
def dispatch_request(self, request):
return Response('Hello World!')
def wsgi_app(self, environ, start_response):
request = Request(environ)
response = self.dispatch_request(request)
return response(environ, start_response)
def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)
def create_app(redis_host='localhost', redis_port=6379, with_static=True):
app = Shortly({
'redis_host': redis_host,
'redis_port': redis_port
})
if with_static:
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/static': os.path.join(os.path.dirname(__file__), 'static')
})
return app
那里发生了什么?为什么将app.wsgi_app分配给SharedDataMiddleware返回的内容?我的意思是,不是app.wsgi_app只是一个方法名吗?
任何见解将不胜感激:)谢谢!
答案 0 :(得分:0)
TL; DR 在此示例中,通过使用Shortly
对象包装其入口点,将额外的功能添加到SharedDataMiddleware
应用。
app.wsgi_app
不是方法名称。它是对该方法的参考。由于Python是非常动态的语言,因此可以在创建此对象后替换任何对象的方法。
让我们考虑一个简单的例子:
class App:
def run(self, param):
print(param)
app = App()
app.run('foo') # prints 'foo'
original_run = app.run # save a reference to the original run method
def run_ex(param):
print('run_ex') # add our extra functionality
original_run(param) # call the original one
app.run = run_ex
app.run('foo') # prints 'run_ex' and then 'foo'
因此,通过这种方式,可以使用常规函数轻松替换app的方法run
。
现在,让我们回到Werkzeug
。如您所知WSGI
specification,应用程序必须是具有特定签名的可调用。 Shortly
wsgi_app
方法是理想的可调用方法。但是,有人希望通过Shortly
中间件向SharedDataMiddleware
应用添加额外的功能。如果你look closer,那么你会发现它是一个使用__call__
方法的常规课程。因此,可以调用SharedDataMiddleware
类的所有对象。
middleware = SharedDataMiddleware(...) # create an object
middleware(...) # call the object. It can be slightly confusing at a first glance
因此,现在您可以看到SharedDataMiddleware
的任何对象本身都是WSGI
个应用程序。既然您已经知道如何替换app
的主要方法wsgi_app
,那么您唯一需要做的就是存储对原始方法Shortly.wsgi_app
的引用能够以后再打电话。通过将其传递给SharedDataMiddleware
构造函数来完成。