Django模型实例外键在状态更改期间失去一致性的列表

2024-09-29 23:25:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模型,Match,有两个外键:

class Match(model.Model):
   winner = models.ForeignKey(Player)
   loser = models.ForeignKey(Player)

当我循环Match时,我发现每个模型实例都为外键使用一个唯一的对象。这最后咬了我,因为它引入了不一致性,下面是一个例子:

^{pr2}$

我是这样解决这个问题的:

def unify_refrences(match_list):
    """Makes each unique refrence to a model instance non-unique.

    In cases where multiple model instances are being used django creates a new
    object for each model instance, even if it that means creating the same
    instance twice. If one of these objects has its state changed any other
    object refrencing the same model instance will not be updated. This method
    ensure that state changes are seen. It makes sure that variables which hold
    objects pointing to the same model all hold the same object.

    Visually this means that a list of [var1, var2] whose internals look like so:

        var1 --> object1 --> model1
        var2 --> object2 --> model1

    Will result in the internals being changed so that:

        var1 --> object1 --> model1
        var2 ------^
    """
    match_dict = {}
    for match in match_list:
        try:
            match.winner = match_dict[match.winner.id]
        except KeyError:
            match_dict[match.winner.id] = match.winner
        try:
            match.loser = match_dict[match.loser.id]
        except KeyError:
            match_dict[match.loser.id] = match.loser

我的问题:有没有一种方法可以更优雅地通过使用QuerySets来解决这个问题,而不需要在任何时候调用save?如果没有,我想让解决方案更通用:如何获得模型实例上的外键列表,或者您有更好的通用解决方案来解决我的问题?在

如果你认为我不明白为什么会这样,请纠正我。在


Tags: theinstance模型idmodelthatobjectmatch
3条回答

这是因为,据我所知,模型实例没有全局缓存,所以每个查询都会创建新的实例,而相关的objct列表是使用单独的查询懒洋洋地创建的。在

您可能会发现select_related()足够聪明,可以解决本例中的问题。而不是像这样的代码:

match = Match.objects.filter(...).get()

使用:

^{pr2}$

一次创建所有属性实例,并且可能足够智能以重用实例。否则,您将需要某种显式缓存(您的解决方案就是这样做的)。在

警告:我自己对这种行为感到惊讶,我不是这方面的专家。我在自己的代码中搜索这类问题的信息时发现了这篇文章。我只是想和大家分享我想知道的事情。。。在

您可能需要检查django-idmapper它定义了一个SharedMemoryModel,这样解释器中每个实例只有一个副本。在

呃,你是用get_or_create()来记录玩家的吗?如果没有,那么您可能正在为每一场比赛创建相同(或几乎相同)球员记录的新实例。这会导致流泪和/或精神错乱。在

相关问题 更多 >

    热门问题