跳转到主要内容

Django ORM的身份映射器

项目描述

© 2014-2017 Thomas Khyn © 2009 David Cramer

这是Django ORM的身份映射器。这是对不再维护的django-idmapper的分支。

已针对django 1.8、1.11和2.0以及Python 2和3的最新次要版本(仅Django 2.0支持Python 3)进行测试。

如果你喜欢django-gm2m,并想感谢我/鼓励未来的开发,以下是我的BTC或BCH捐赠地址:1EwENyR8RV6tMc1hsLTkPURtn5wJgaBfG9

这是什么?

django-idmap是一个Django应用程序,

  • 首次需要时在内存中仅加载一次实例

  • 在整个解释器中共享,直到请求完成

实际上,Django的默认行为是在请求的开始和结束之间暴露不同的实例。这有一个主要后果:如果你想在代码的另一个地方访问相同的数据库对象,你设置的临时属性将会丢失。

已与django 1.8+以及python 2和3的最新次要版本进行测试。

安装

使用pip,尽可能简单

pip install django-idmap

您还需要将'idmap'添加到INSTALLED_APPS设置中。

快速入门

要启用模型的身份映射器,您只需将其继承自 idmap.models.IdMapModel 而不是 django.db.models.Model 即可。

当然,您可以将 IdMapModelModel 混合使用。

from idmap import models

class MyModel(models.IdMapModel):
    name = models.CharField(...)
    fkey = models.ForeignKey('Other', on_delete=models.CASCADE)

class Other(models.Model):
    name = models.CharField(...)

有 2 种缓存模式可用

  • 弱引用模式:一旦没有更多的引用指向它,实例将从缓存中删除。这是默认行为。

  • 强引用模式:实例将只从数据库加载一次,并在刷新时从缓存中删除。

如果您想为特定模型使用强引用,只需在派生模型类的 Meta 中将 use_strong_refs 设置为 True 即可。

from idmap import models

class MyModel(models.IdMapModel):
   class Meta:
      use_strong_refs = True
   [...]

手动操作

在大多数情况下,这就是使用 django-idmap 所要做的。有时,在请求完成之前,您可能需要手动刷新缓存。

您可以使用

  • idmap.flush() 来清除整个缓存

  • IdMapModel.flush_instance_cache() 来清除一个模型的缓存

  • IdMapModel.flush_cached_instance(instance) 来从缓存中清除一个实例

信号

idmap.signals.pre_flushidmap.signals.post_flush 分别在缓存刷新之前和之后发送。如果需要在这些时刻运行代码,请将这些处理程序连接到这些信号。

django-idmap 在发送 request_finishedpost_migrate 信号时刷新缓存。可以通过断开 idmap.signals.flush_idmap 处理程序与这些信号的联系来修改此默认行为(风险自担!)。

多数据库支持

在某些情况下,您可能需要将同一模型的实例存储在多个数据库中。您可以让 django-idmap 在创建或获取实例时也考虑数据库。

class MyModel(models.IdMapModel):
   class Meta:
      multi_db = True
   [...]

这样,数据库 db1 中主键为 1instance1_1 将与数据库 db2 中主键为 1instance2_1 不同。

>>> MyModel.objects.using('db1').create(pk=1)
>>> MyModel.objects.using('db2').create(pk=1)
>>> idmap.flush()
>>> instance1_1 = MyModel.objects.using('db1').get(pk=1)
>>> instance2_1 = MyModel.objects.using('db2').get(pk=1)
>>> assert instance1_1 is instance 2_1
AssertionError

在使用多个数据库时,您也可以通过向 idmap.flush() 提供数据库名称来仅刷新一个数据库。

>>> idmap.flush('db1')

这将仅刷新使用数据库 db1 获取的实例。 IdMapModel.flush_instance_cache 也可以接受一个 db 参数。

同样,当发送 pre_flushpost_flush 信号时,提供了一个关键字参数 db。如果刷新所有数据库(即如果没有提供数据库别名),则 dbNone

代理模型

使用相同的基础具体类(我们称之为代理族)的所有模型和代理模型的实例都存储在同一个缓存中,并且可以通过代理族的成员访问。

>>> class MyProxyModel(MyModel):
>>>     class Meta:
>>>         proxy = True
>>> original = MyModel.objects.create(pk=1)
>>> proxy = MyProxyModel.objects.create(pk=2)
>>> assert original is MyProxyModel.get(pk=1)

继承追击

如果您需要在基于 IdMapModel 的模型上使用自定义管理器或自定义元类,则需要从 idmap 的自己的管理器和元类派生它们。

>>> class MyModelBase(models.IdMapModelBase):
>>>     [...]
>>> class MyManager(models.IdMapManager):
>>>     [...]
>>> class MyModel(models.IdMapModel,
                  metaclass=MyModelBase): # on python 3
>>>     __metaclass__ = MyModelBase  # on python 2
>>>     objects = MyManager()

参考

David Cramer 的 django-idmapper

原始代码和概念:http://code.djangoproject.com/ticket/17

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。

源分布

django-idmap-1.0.3.tar.gz (13.2 kB 查看散列)

上传时间

由以下支持