Django - 根据请求收集信息

时间:2017-11-14 15:50:48

标签: python django singleton

我想在每个请求中收集数据(单个请求可能会导致多处更改),并在请求结束时处理数据。

所以我使用单例类来收集数据,并且我在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()

2 个答案:

答案 0 :(得分:2)

单例意味着每个进程只有一个实例。典型的生产Django设置是一个或多个前端服务器运行多个长时间运行的Django进程,每个进程服务任何传入的请求。 FWIW你甚至可以在同一进程AFAICT中的并发线程中提供Django。在这种情况下,同一个用户可以拥有由不同进程/线程提供的后续请求,以及任何长期存在的全局'对象将由当前进程提供的所有请求共享。最终结果是,丹尼尔罗斯曼正确评论说,单身人士将永远不会像Django"这样的多进程多用户环境中做你想做的事。

如果您想收集每个请求 - 响应周期数据,最好的办法是将它们存储在request对象本身上,使用中间件在请求处理周期开始时初始化收集器并对收集的内容执行某些操作请求处理周期结束的数据。这当然需要一直传递请求......这确实有点笨拙。

此处的解决方法可能是连接您的每个请求"收集器"对象的方法作为信号处理程序,负责正确设置" dispatch_uid"所以你可以在发送响应之前断开它们,最好使用弱引用来避免内存泄漏。

注意:如果你想收集每个用户的信息,那就是session框架的用途,但我想你已经理解了这一点。

答案 1 :(得分:1)

  • 编辑我的答案,第一个没想好。

在进一步思考之后,在信号中使用请求并不是一个好主意,既不是全局也不是传递它。

Django有两条主要路径:视图和命令。视图用于Web请求,即生成“请求”对象。命令通过控制台使用,不生成“请求”对象。理想情况下,您的模型(因此也是信号)应该能够支持两个路径(例如:在项目的生命周期内进行数据迁移)。因此,将信号绑定到请求对象本身就是不正确的。

最好使用线程本地内存空间之类的东西,并确保您的线程全局类不依赖于请求中的任何内容。例如: Is there a way to access the context from everywhere in Django?