Python 我可以将Django模型对象作为单例获取吗?

Python 我可以将Django模型对象作为单例获取吗?,python,django,django-models,Python,Django,Django Models,当我为同一id调用Models.get()时,它会返回不同的Python对象: print(Book.objects.get(id=1) is Book.objects.get(id=1)) >>> False 我想知道是否有可能改变这种行为,也许可以使用一些自定义模型管理器。它可以在内部为所有检索到的对象存储一些注册表,并覆盖get\u queryset(),以便在已经检索到这些对象时使用此注册表中的对象 为什么这样做会有帮助 我有一个存储登录名和密码的型号ServerCr

当我为同一id调用
Models.get()
时,它会返回不同的Python对象:

print(Book.objects.get(id=1) is Book.objects.get(id=1))
>>> False
我想知道是否有可能改变这种行为,也许可以使用一些自定义模型管理器。它可以在内部为所有检索到的对象存储一些注册表,并覆盖
get\u queryset()
,以便在已经检索到这些对象时使用此注册表中的对象

为什么这样做会有帮助

我有一个存储登录名和密码的型号
ServerCredentials
。我有多个消费者使用相同的凭据进行连接。由于只允许与服务器建立一个连接,因此可以方便地将临时连接信息(例如身份验证令牌)存储为
ServerCredentials
对象的字段,但不存储在数据库中。如果模型对象可以是单例的,那么消费者只需使用
ServerCredentials
字段就可以轻松地共享身份验证令牌。没有它,我必须手动创建一些注册表,但我认为应该在
ModelManager的
端完成

  • 是否可以在
    ModelManager的
    侧的注册表中缓存对象
  • 这是个好主意吗
  • 有实现吗

  • 非常感谢

    模型的管理器是其各自类的常规实例,因此可以实现某种类型的注册表。但是,每个进程的此注册表都是唯一的。在生产环境中,应用程序通常由启动多个进程(例如uwsgi)的服务器运行(甚至在多台机器上运行)


    如果要使瞬态数据在整个应用程序中可用,您可以将Django的缓存功能与内存存储(如Memcached或Redis)结合使用。

    我认为您应该了解一下apache/nginx如何处理每个请求的进程,因为即使您可以使用单例模式,它也无法工作,因为可能会有多个进程同时运行,每个进程针对不同的请求和每个请求该进程的所有部分在内存中都有自己的单例/缓存/注册表。下面描述了实现每个进程缓存的一种方法

    我们在系统中缓存数据的方法是在类本身上使用静态变量来缓存数据,因为它在每个会话中都存储,这取决于http服务器的配置方式(仅在每个进程中缓存)

    现在,您可以使用此缓存读取数据,因为数据只会在填充缓存后读取。如果需要,您还可以刷新缓存


    您必须按照其他答案的建议使用memcache或redis来满足您的确切需求(所有进程都使用相同的缓存)。

    为什么要使用
    is
    运算符,而不是使用
    =
    检查相等性?后者有效,而且似乎可以满足您的需求<代码>是是对对象标识的测试,而不是对相等性的测试。@但我需要对象相等性,因为我希望它们共享非数据库字段。例如,
    Book.objects.get(id=1).some\u field=“foo”;assert(Book.objects.get(id=1)。some_field==“foo”)
    不保存到数据库每个进程都是唯一的,因为我的应用程序不是多进程的:)那么,我应该创建一些
    CachedManager(models.Manager)
    ,重写
    get_queryset()
    并在那里使用一些自定义的
    queryset
    类来进行缓存吗?据我所知,对象必须在该自定义
    QuerySet
    \uuuuu iter\uuuuu
    中的缓存中,只要它是检索对象的地方@Daniel Hepper,ides正确吗?@sckol我想我的答案不清楚,我已经重新编写了它在我的特殊情况下,它只是一个进程,因为单例注册表仅用于管理任务(单后台数据下载进程),而该任务从未由HTTP请求启动。但是你的回答让我明白了为什么没有简单的解决方案-一般情况下,它应该关心进程之间的注册表共享。每次检索对象时,你是否手动调用
    populate\u cache
    ?在上面的评论中,我提出了一个建议:创建一些CachedManager(models.Manager),重写get_queryset(),并在那里使用一些定制的queryset类来进行缓存。你认为这是一个正确的方法吗?每个进程的缓存是可以的。只有在尚未填充时才调用populate_cache。我通常基于唯一值(e.f username)为缓存设置键,以查看其是否已缓存,但您可以检查其是否为空或在缓存中搜索值,这在很大程度上取决于您的表结构。因此,您可以将函数设为\u cache\uempty(),以确定其是否为空。是的,您也可以在ObjectManager上使用它,只需确保按一个或多个唯一字段为缓存设置关键帧,您不能缓存所有查询集,尽管只缓存某个已知查询的结果。
    Class SomeModel(models.Model):
        CACHE_DATA = {} # you can use any other container but dicts are best if its keyable
        # write functions to populate this cache and read from this cache
        def populate_cache():
            # populate only its empty
            if SomeModel.is_cache_empty(key):
               # populate the Cache here
    
        def is_cache_empty(key):
            if key not in SomeModel.CACHE_DATA:
                return True
            else:
                return False
    
    
        def read_data_from_cache():
            # read based on key or some other you may use a linear search for a list e.g.