List of Django model instance foreign keys losing consistency during state changes.

Posted by Joshua on Stack Overflow See other posts from Stack Overflow or by Joshua
Published on 2010-06-11T02:58:31Z Indexed on 2010/06/11 3:02 UTC
Read the original article Hit count: 329

I have model, Match, with two foreign keys:

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

When I loop over Match I find that each model instance uses a unique object for the foreign key. This ends up biting me because it introduces inconsistency, here is an example:

>>> 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
>>>

I solved this problem like so:

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

My question: Is there a way to solve the problem more elegantly through the use of QuerySets without needing to call save at any point? If not, I'd like to make the solution more generic: how can you get a list of the foreign keys on a model instance or do you have a better generic solution to my problem?

Please correct me if you think I don't understand why this is happening.

© Stack Overflow or respective owner

Related posts about python

Related posts about django