diff options
| author | Anssi Kääriäinen <akaariai@gmail.com> | 2013-08-14 11:05:01 +0300 |
|---|---|---|
| committer | Anssi Kääriäinen <akaariai@gmail.com> | 2013-08-22 17:24:07 +0300 |
| commit | 6af05e7a0f0e4604d6a67899acaa99d73ec0dfaa (patch) | |
| tree | de9bc5025ba6062a3ff71cb234c6e0c84a9daf9c /django | |
| parent | 768bbf3efe0c412bced1e865e90139a0f07dc613 (diff) | |
Fixed model.__eq__ and __hash__ for no pk value cases
The __eq__ method now considers two instances without primary key value
equal only when they have same id(). The __hash__ method raises
TypeError for no primary key case.
Fixed #18864, fixed #18250
Thanks to Tim Graham for docs review.
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/base.py | 13 | ||||
| -rw-r--r-- | django/forms/models.py | 6 |
2 files changed, 15 insertions, 4 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py index 3e2ae8d425..a5b0f188b4 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -459,14 +459,21 @@ class Model(six.with_metaclass(ModelBase)): return '%s object' % self.__class__.__name__ def __eq__(self, other): - return (isinstance(other, Model) and - self._meta.concrete_model == other._meta.concrete_model and - self._get_pk_val() == other._get_pk_val()) + if not isinstance(other, Model): + return False + if self._meta.concrete_model != other._meta.concrete_model: + return False + my_pk = self._get_pk_val() + if my_pk is None: + return self is other + return my_pk == other._get_pk_val() def __ne__(self, other): return not self.__eq__(other) def __hash__(self): + if self._get_pk_val() is None: + raise TypeError("Model instances without primary key value are unhashable") return hash(self._get_pk_val()) def __reduce__(self): diff --git a/django/forms/models.py b/django/forms/models.py index a5b82e521d..4c6ee9c6ed 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -631,7 +631,11 @@ class BaseModelFormSet(BaseFormSet): seen_data = set() for form in valid_forms: # get data for each field of each of unique_check - row_data = tuple([form.cleaned_data[field] for field in unique_check if field in form.cleaned_data]) + row_data = (form.cleaned_data[field] + for field in unique_check if field in form.cleaned_data) + # Reduce Model instances to their primary key values + row_data = tuple(d._get_pk_val() if hasattr(d, '_get_pk_val') else d + for d in row_data) if row_data and not None in row_data: # if we've already seen it then we have a uniqueness failure if row_data in seen_data: |
