flask-restful - 当前请求的资源 class
flask-restful - resource class for current request
问题
我的应用程序的所有路由都是通过 flask-restful 资源定义的。
如何找到正在处理当前请求的资源 object/class?
为什么我想要这个
我想记录处理请求时引发的所有异常。我连接到 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)
唯一的问题是我想记录一些请求数据,但不是所有数据 - 例如我想隐藏密码。我认为将日志记录数据逻辑与请求处理逻辑结合在一起是个好主意,如下所示:
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!'}
然后在我的 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)
但也许这应该以其他方式完成?
一旦信号调用了日志记录方法,我就找不到访问对象的好方法。
如果您愿意处理所有可能的情况,您可以创建自己的自定义异常,在 class.
上调用 log_data 方法
相反,我选择处理自己在基地 class 中的记录。给你的简单例子,我只是使用了打印函数,但你可以调用 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, "/")
如果您想更深入地研究 flask restful 源代码,您还可以猴子修补(或构建您自己的包)任何方法正在调用 get/post。
您不想从 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
然后你可以使用异常处理器
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__))
这是我试过的完整代码
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:8 月 5 日
正如@jbet 所评论的,如果有人想要处理 class 总是一个更清晰的选择是使用 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)
问题
我的应用程序的所有路由都是通过 flask-restful 资源定义的。 如何找到正在处理当前请求的资源 object/class?
为什么我想要这个
我想记录处理请求时引发的所有异常。我连接到 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)
唯一的问题是我想记录一些请求数据,但不是所有数据 - 例如我想隐藏密码。我认为将日志记录数据逻辑与请求处理逻辑结合在一起是个好主意,如下所示:
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!'}
然后在我的 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)
但也许这应该以其他方式完成?
一旦信号调用了日志记录方法,我就找不到访问对象的好方法。
如果您愿意处理所有可能的情况,您可以创建自己的自定义异常,在 class.
上调用 log_data 方法相反,我选择处理自己在基地 class 中的记录。给你的简单例子,我只是使用了打印函数,但你可以调用 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, "/")
如果您想更深入地研究 flask restful 源代码,您还可以猴子修补(或构建您自己的包)任何方法正在调用 get/post。
您不想从 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
然后你可以使用异常处理器
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__))
这是我试过的完整代码
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:8 月 5 日
正如@jbet 所评论的,如果有人想要处理 class 总是一个更清晰的选择是使用 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)