在Django中刷新模型的非托管相关模型

时间:2012-10-25 13:53:56

标签: django orm

我有一个模型(让我们称之为实体),它具有随时间变化的属性(Attribute),但我想保留该属性在数据库中如何变化的历史记录。我需要能够通过其管理器中的Attribute的当前值来过滤我的实体。但是因为Django(据我所知)不允许我在本地查询中执行此操作,所以我创建了一个数据库视图,为每个实体生成最新的Attribute值。所以我的模型结构看起来像这样:

class Entity(models.Model):
    def set_attribute(self, value):
        self.attribute_history.create(value=value)

    def is_attribute_positive(self, value):
        return self.attribute.value > 0

class AttributeEntry(models.Model):
    entity = models.ForeignKey(Entity, related_name='attribute_history')
    value = models.IntegerField()
    time = models.DateTimeField(auto_now_add=True)

class AttributeView(models.Model)
    id = models.IntegerField(primary_key=True, db_column='id', 
        on_delete=models.DO_NOTHING)
    entity = models.OneToOneField(Entity, related_name='attribute')
    value = models.IntegerField()
    time = models.DateTimeField()

    class Meta:
        managed = False

我的数据库具有生成当前属性的视图,使用SQL创建,如下所示:

CREATE VIEW myapp_attributeview AS
SELECT h1.*
FROM myapp_attributehistory h1
LEFT OUTER JOIN myapp_attributehistory h2
    ON h1.entity_id = h2.entity_id
        AND (h1.time < h2.time
        OR h1.time = h2.time
        AND h1.id < h2.id)
WHERE h2.id IS NULL;

我的问题是,如果我使用set_attribute()在模型对象上设置属性并使用is_attribute_positive()进行检查并不总是有效,因为Django可能正在缓存相关的AttributeView对象。我怎么能让Django更新它的模型,至少通过重新查看视图?我能否以某种方式将attribute属性标记为脏?

PS:我这样做的全部原因是我可以做Entity.objects.filter(attribute__value__exact=...).filter(...)这样的事情,所以如果有人知道更简单的方法来获得这个功能,那么这样的答案也会被接受!

2 个答案:

答案 0 :(得分:0)

据我所知,属性值被另一个访问相同数据库的进程(甚至可能不是Django)修改。如果不是这种情况,您应该查看django-reversion

另一方面,如果是这种情况,你应该看看this的第二个答案。它表示提交事务使查询缓存无效并提供此代码段。

>>> from django.db import transaction
>>> transaction.enter_transaction_management()
>>> transaction.commit() # Whenever you want to see new data

答案 1 :(得分:0)

我从未直接解决过问题,但我可以通过更改is_attribute_positiive()来直接查询数据库表而不是视图来回避它。

def is_attribute_positive(self, value):
    return self.attribute_history.latest().value > 0

因此,虽然视图为我提供了在Entity上过滤查询的灵活性,但是一旦收到对象,最好直接在表支持的模型上运行。