Django

Code

Ticket #2936 (closed: fixed)

Opened 2 years ago

Last modified 5 months ago

[patch]override __hash__ method of django.db.base.Model

Reported by: favo@exoweb.net Assigned to: adrian
Milestone: Component: Database wrapper
Version: SVN Keywords:
Cc: favo@exoweb.net, canburak@cs.bilgi.edu.tr Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

Since django Model has override __eq__ method, should override __hash__ method too (objects comparing equal should also hash to the same value).

Attachments

add_hash_to_model.diff (0.5 kB) - added by favo@exoweb.net on 10/19/06 21:55:26.
add hash to django.db.model.base

Change History

10/19/06 21:55:26 changed by favo@exoweb.net

  • attachment add_hash_to_model.diff added.

add hash to django.db.model.base

10/19/06 21:56:51 changed by anonymous

  • summary changed from override __hash__ method of django.db.base.Model to [patch]override __hash__ method of django.db.base.Model.

10/19/06 22:27:56 changed by jim-django@dsdd.org

There's no need to stringify the primary key before hashing, is there?

10/20/06 00:35:19 changed by favo@exoweb.net

hmm... I just remember some strange situation that I meet. anyway it seems no need.

10/21/06 10:23:34 changed by favo@exoweb.net

  • status changed from new to closed.
  • resolution set to invalid.

I was totally wrong to open this ticket, since http://docs.python.org/ref/customization.html:

  If a class defines mutable objects and implements a __cmp__() or __eq__() method, 
it should not implement __hash__()

And django model is a mutable object. so we can't implement __hash__().

02/15/07 14:48:20 changed by Ned Batchelder <ned@nedbatchelder.com>

I think in this case the Python docs were mis-interpreted. The key point to consider when writing a hash function is that two objects that compare equal must hash equally, and the hash value cannot change. Just because an object is mutable doesn't mean that these rules will be violated. A mutable object may have a hash that uses its mutable data as part of the hash implementation, which would be unacceptable. But a mutable object can have a carefully planned hash which only uses the immutable data in its calculation.

In particular, Django model instances will usually simply use their id attribute as the hash, and so will be perfectly acceptable as dictionary keys.

06/28/07 13:41:59 changed by vdupras@goombah.com

I agree with Ned here, I would expect len(set([Model.objects.get(pk=1), Model.objects.get(pk=1)])) to be 1, but it's 2. I'd be inclined to consider it as a bug.

11/14/07 21:23:44 changed by Jim Crossley <jcrossley@websingularity.com>

  • status changed from closed to reopened.
  • resolution deleted.

I concur. Using sets to filter duplicates is a common, efficient idiom. We should be able to do the same with model instances, mutable or not. The very fact that model equality is determined by their id alone makes the question of mutability irrelevant.

Consider a contrived example:

x = set(Foo.objects.all())
for f in Foo.objects.all():
  x.add(f)

As it now stands, you'll end up with two copies of each Foo model in the set, a clear violation of the "principle of least surprise", IMHO.

11/15/07 01:59:09 changed by mir

Please, could you send an email to django-developers? I think this has been rejected by the core developers, but your arguments are valid.

11/15/07 02:50:25 changed by mtredinnick

  • stage changed from Unreviewed to Accepted.

It hasn't been rejected. There's no need for an email, it's a reasonable request. The original ticket burned and died based on mistaken assumptions (as Ned correctly notes) and just never got onto the radar.

01/12/08 16:16:33 changed by Can Burak Cilingir <canburak@cs.bilgi.edu.tr>

  • cc changed from favo@exoweb.net to favo@exoweb.net, canburak@cs.bilgi.edu.tr.

02/18/08 19:59:34 changed by mtredinnick

  • status changed from reopened to closed.
  • resolution set to fixed.

(In [7132]) Fixed #2936, #6500 -- Added a hash() method to Models (since we implement our own eq method).


Add/Change #2936 ([patch]override __hash__ method of django.db.base.Model)




Change Properties
Action