编程语言
首页 > 编程语言> > python-状态更改期间失去一致性的Django模型实例外键列表

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

作者:互联网

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

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

当我遍历Match时,我发现每个模型实例都使用一个唯一的对象作为外键.由于引入了不一致性,这最终使我感到痛苦,这是一个示例:

>>> def print_elo(match_list):
...     for match in match_list:
...         print match.winner.id, match.winner.elo
...         print match.loser.id, match.loser.elo
... 
>>> print_elo(teacher_match_list)
4 1192.0000000000
2 1192.0000000000
5 1208.0000000000
2 1192.0000000000
5 1208.0000000000
4 1192.0000000000
>>> teacher_match_list[0].winner.elo = 3000
>>> print_elo(teacher_match_list) 
4 3000            # Object 4
2 1192.0000000000
5 1208.0000000000
2 1192.0000000000
5 1208.0000000000
4 1192.0000000000 # Object 4
>>>

我这样解决了这个问题:

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

我的问题:有没有一种方法可以通过使用QuerySet来更优雅地解决问题,而无需随时调用save?如果不是,我想使解决方案更通用:如何获取模型实例上的外键列表,或者您有更好的通用解决方案来解决我的问题?

如果您认为我不明白为什么会发生,请纠正我.

解决方法:

据我所知,这是因为,没有模型实例的全局高速缓存,因此每个查询都会创建一个新实例,并且相关对象的列表是使用单独的查询延迟创建的.

您可能会发现select_related()非常聪明,可以解决这种情况下的问题.而不是像这样的代码:

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

采用:

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

这将立即创建所有属性实例,并且可能足够聪明以重新使用实例.否则,您将需要某种显式缓存(这是您的解决方案所要做的).

警告:我自己对这种行为感到惊讶,而不是专家.我在自己的代码中搜索有关此类问题的信息时找到了这篇文章.我只是在分享我想了解的事情…

标签:foreign-keys,python,django,django-models
来源: https://codeday.me/bug/20191210/2098423.html