【问题标题】:Refreshing a model's unmanaged related model in Django在 Django 中刷新模型的非托管相关模型
【发布时间】:2012-10-15 17:31:30
【问题描述】:

我有一个模型(我们称之为实体),它有一个随时间变化的属性(属性),但我想保留数据库中该属性如何变化的历史记录。我需要能够通过其管理器中 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(...) 这样的事情,所以如果有人知道更简单的方法来获得该功能,那么这样的答案也会被接受!

【问题讨论】:

    标签: django orm


    【解决方案1】:

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

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

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

    【讨论】:

    • 属性在视图下的表中被修改。问题是 Django 不知道模型是由视图支持的,因此它认为没有理由重新查询。您提供的链接对我的情况没有帮助,因为我实际上正在执行实体本身的设置和签入方法,因此我没有明显的方法为 self.attribute 请求新的查询集
    【解决方案2】:

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

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

    因此,虽然视图让我能够灵活地过滤实体上的查询,但一旦收到对象,最好的办法似乎是直接在表支持的模型上进行操作。

    【讨论】:

      猜你喜欢
      • 2014-07-02
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      相关资源
      最近更新 更多