AlanL
AlanL

Reputation: 636

Django: overridden __hash__ not working for objects from database?

I have a problem with django model objects where I have overridden __hash__() for some slightly complex uniqueness/distinctiveness constraints that I want to enforce when I use them. This is working fine with objects that I have just directly instantiated in memory, but not with ones I retrieve from the database.

Like this:

class Animal(models.Model):
    name = model.Charfield('name', max_length=10)

    def__hash__(self):
        return len(self.name) # silly example for purposes of illustration

and then this:

>> a = models.Animal(name='cat')
>> b = models.Animal(name='dog')
>> len(set((a,b))
> 1
>> a.save()
>> b.save()
>> len(set(models.Animal.objects.all()))
> 2

Hmm. Whatever hash function is being used here, it ain't mine. I guess it's something related to lazy fetching / objects not yet in a fully instantiated state, but how to get round it?

Upvotes: 0

Views: 366

Answers (1)

David Wolever
David Wolever

Reputation: 154504

This is because you have implemented __hash__ without implementing __eq__. Implement __eq__ as well and you should be good to go.

The length of set([a, b]) is 1 because Django defines a default __eq__ function which compares the primary keys of the objects — so before they are saved, both with have an id of None, so a == b will be True. After they are saved, they will both have been assigned different primary keys, so a != b will be True.

Upvotes: 3

Related Questions