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?
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])is1because Django defines a default__eq__function which compares the primary keys of the objects — so before they are saved, both with have anidofNone, soa == bwill beTrue. After they are saved, they will both have been assigned different primary keys, soa != bwill beTrue.