我希望收集每个请求中的数据(单个请求可能会导致多个更改),并在请求结束时处理数据。
所以我使用一个单例类来收集数据,并在request_finished信号上处理其中的数据。它是否应该工作,或者我是否应该预料到数据丢失/其他问题?
单例类:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class DataManager(object, metaclass=Singleton):
....在其他信号中使用它:
item_created = DataManager().ItemCreated(item)
DataManager().add_event_to_list(item_created)请求完成信号:
@receiver(request_finished, dispatch_uid="request_finished")
def my_request_finished_handler(sender, **kwargs):
DataManager().process_data()发布于 2017-11-15 00:14:45
单例意味着每个进程只有一个实例。典型的生产Django设置是一个或多个前端服务器运行多个长时间运行的Django进程,每个进程都为任何传入的请求提供服务。FWIW你甚至可以在同一进程AFAICT的并发线程中为Django提供服务。在这种情况下,同一个用户的后续请求可以由不同的进程/线程服务,并且任何长期存在的“全局”对象都将由当前进程服务的所有请求共享。最终的结果是,正如Daniel Roseman正确地评论的那样,“在Django这样的多进程多用户环境中,单例永远不会做你想要的事情”。
如果您想收集每个请求-响应周期的数据,最好的方法是将它们存储在request对象本身上,在请求处理周期开始时使用中间件初始化收集器,并在请求处理周期结束时对收集的数据执行某些操作。当然,这需要一直传递请求...这确实有点笨拙。
这里的一个解决方法可能是将每个请求的“收集器”对象的一些方法连接为信号处理程序,注意正确设置"dispatch_uid“以便在发送响应之前断开它们,并且最好使用弱引用来避免内存泄漏。
注意:如果您想收集每个用户的信息,这就是session框架的作用,但我假设您已经了解这一点。
发布于 2017-11-15 15:05:46
经过进一步的思考,在信号中使用请求并不是一个好主意,既不是全局的,也不是传递的。
Django有两个主要路径:视图和命令。视图用于web请求,它生成一个“request”对象。命令是通过控制台使用的,不会生成“request”对象。理想情况下,您的模型(因此,也是信号)应该能够支持两种路径(例如:在项目生命周期内进行数据迁移)。因此,将您的信号绑定到请求对象本身就是不正确的。
最好使用类似线程本地内存空间的东西,并确保线程全局类不依赖于请求中的任何内容。例如:Is there a way to access the context from everywhere in Django?
https://stackoverflow.com/questions/47289951
复制相似问题