[英]flask-restful - resource class for current request
THE QUESTION 问题
All of my app's routes are defined via flask-restful Resources. 我所有应用程序的路由都是通过flask-restful Resources定义的。 How can I find the resource object/class that is processing current request?
如何找到处理当前请求的资源对象/类?
WHY I WANT THIS 为什么我想要这个
I wanted to log all exceptions raised while processing requests. 我想记录处理请求时引发的所有异常。 I connect to
flask.got_request_exception
, as described in http://flask.pocoo.org/docs/1.0/api/#signals and something like this works well: 我连接到
flask.got_request_exception
,如http://flask.pocoo.org/docs/1.0/api/#signals中所述,这样的效果很好:
from flask import got_request_exception, request
def log_exception(sender, exception, **extra):
logger.info("URL: {}, Exception: {}".format(request.url, type(exception).__name__))
got_request_exception.connect(log_exception, app)
The only problem is that I want to log some of the request data, but not all the data - eg I'd like to hide passwords. 唯一的问题是我想记录一些请求数据,但不是所有数据 - 例如我想隐藏密码。 I think it would be a good idea to have logging-data-logic together with request processing logic, like this:
我认为将日志记录数据逻辑与请求处理逻辑结合在一起是个好主意,如下所示:
from flask import request
import flask_restful
class SomeResource(flask_restful.Resource):
def get(self):
# ... GET processing
def log_data(self):
# log all body params
return request.get_json()
class Login(flask_restful.Resource):
def post(self):
# ... authentication
def log_data(self):
# log selected body params
return {'login': request.get_json()['login'], 'password': 'HIDDEN!'}
and than use it in my log_exception
: 而不是在我的
log_exception
使用它:
from flask import got_request_exception, request
def log_exception(sender, exception, **extra):
resource_class = # THIS IS THE THING I'M MISSING
logger.info("URL: {}, Exception: {}, Data: {}".format(request.url, type(exception).__name__),
resource_class.log_data())
got_request_exception.connect(log_exception, app)
But maybe this should be done other way? 但也许这应该以其他方式完成?
Instead of inheriting from flask_restful.Resource
your want to inherit all from a custom resource 您希望从自定义资源继承所有内容,而不是继承
flask_restful.Resource
class MyResource(flask_restful.Resource):
def dispatch_request(self, *args, **kwargs):
try:
return super(MyResource,self).dispatch_request(*args, **kwargs)
except Exception as ex:
setattr(ex, "_raised_by", self)
raise ex
and then you can use the exception handler 然后你可以使用异常处理程序
def log_exception(sender, exception, **extra):
_raised_by = getattr(exception, "_raised_by", None)
if _raised_by:
print(_raised_by)
property("URL: {}, Exception: {}".format(request.url, type(exception).__name__))
Here is complete code I tried 这是我试过的完整代码
from flask import request, Flask
import flask_restful
app = Flask(__name__)
api = flask_restful.Api(app)
class MyResource(flask_restful.Resource):
def dispatch_request(self, *args, **kwargs):
try:
return super(MyResource,self).dispatch_request(*args, **kwargs)
except Exception as ex:
setattr(ex, "_raised_by", self)
raise ex
# MyResource = flask_restful.Resource
class SomeResource(MyResource):
def get(self):
raise Exception("Not implemented")
def log_data(self):
# log all body params
return request.get_json()
class Login(MyResource):
def post(self):
raise Exception("Not implemented")
def log_data(self):
# log selected body params
return {'login': request.get_json()['login'], 'password': 'HIDDEN!'}
from flask import got_request_exception, request
api.add_resource(Login, '/login')
api.add_resource(SomeResource, '/some')
def log_exception(sender, exception, **extra):
_raised_by = getattr(exception, "_raised_by", None)
if _raised_by:
print(_raised_by)
property("URL: {}, Exception: {}".format(request.url, type(exception).__name__))
got_request_exception.connect(log_exception, app)
if __name__ == '__main__':
app.run(debug=True)
Edit-1: 5th Aug 编辑1:8月5日
As commented by @jbet, in case one wants to get the processing class always a cleaner option would be to use the MyResource
as below 正如@jbet评论的那样,如果想要获得处理类总是一个更清晰的选项,那就是使用
MyResource
,如下所示
from flask import g
class MyResource(flask_restful.Resource):
def dispatch_request(self, *args, **kwargs):
g.processed_by = self
return super(MyResource,self).dispatch_request(*args, **kwargs)
I could not find a nice way to get access to your object once the logging method had been called by signals. 一旦通过信号调用了日志记录方法,我找不到一种很好的方式来访问您的对象。
If you were willing to handle all possible cases, you could create your own custom exceptions that call the log_data method on your class. 如果您愿意处理所有可能的情况,您可以创建自己的自定义异常,在您的类上调用log_data方法。
Instead, I opted to handle logging myself in a base class. 相反,我选择在基类中处理自己的日志。 Simple example for you, I just used print functions, but you could call app.logging.info instead.
简单的例子,我刚刚使用了打印功能,但你可以调用app.logging.info。
from flask import Flask, request
import flask_restful
app = Flask(__name__)
api = flask_restful.Api(app)
class MyCustomResource(flask_restful.Resource):
def get(self):
try:
self.my_get()
except Exception as exception:
# Will catch all errors in your subclass my_get method
print("exception caught")
print(request.url)
print(type(exception).__name__)
print(self.log_data())
# Re-raise if you want (or not)
raise exception
def my_get(self):
# Python equivalent of virtual method
raise NotImplementedError()
def log_data(self):
# Python equivalent of virtual method
raise NotImplementedError()
class SomeResource(MyCustomResource):
def my_get(self):
# Example unknown error occurs here
raise Exception("error!")
return "some data"
def log_data(self):
# Called by parent
return "some logging data for the object"
api.add_resource(SomeResource, "/")
If you wanted to dig deeper into the flask restful source you could also monkey patch (or build your own package) whatever method is calling get/post. 如果你想更深入地了解烧瓶的源代码,你也可以使用任何方法调用get / post来修补补丁(或构建自己的包)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.