From 008f333bac7ceada4aca06b274a57ede1f8bc3d9 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Thu, 18 Nov 2010 23:29:58 +0000 Subject: [PATCH] Fixed pk uniqueness validation for new objects created outside of a ModelForm. Also removed need for ModelForm to poke at Model._state.adding, keeping it an internal ORM concern. git-svn-id: http://code.djangoproject.com/svn/django/trunk@14613 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/base.py | 2 +- django/db/models/query.py | 4 ++++ django/forms/models.py | 2 -- tests/regressiontests/model_regress/models.py | 2 ++ tests/regressiontests/model_regress/tests.py | 16 +++++++++++++--- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index 44f90a19f7..18a684d715 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -265,7 +265,7 @@ class ModelState(object): # If true, uniqueness validation checks will consider this a new, as-yet-unsaved object. # Necessary for correct validation of new instances of objects with explicit (non-auto) PKs. # This impacts validation only; it has no effect on the actual save. - self.adding = False + self.adding = True class Model(object): __metaclass__ = ModelBase diff --git a/django/db/models/query.py b/django/db/models/query.py index d448dec2bc..25e37cc701 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -284,6 +284,8 @@ class QuerySet(object): # Store the source database of the object obj._state.db = self.db + # This object came from the database; it's not being added. + obj._state.adding = False for i, k in enumerate(extra_select): setattr(obj, k, row[i]) @@ -1204,6 +1206,7 @@ def get_cached_row(klass, row, index_start, using, max_depth=0, cur_depth=0, # If an object was retrieved, set the database state. if obj: obj._state.db = using + obj._state.adding = False index_end = index_start + field_count + offset # Iterate over each related object, populating any @@ -1387,6 +1390,7 @@ class RawQuerySet(object): setattr(instance, field, value) instance._state.db = self.query.using + instance._state.adding = False return instance diff --git a/django/forms/models.py b/django/forms/models.py index 729f523103..4ffc3b6fac 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -254,10 +254,8 @@ class BaseModelForm(BaseForm): # if we didn't get an instance, instantiate a new one self.instance = opts.model() object_data = {} - self.instance._state.adding = True else: self.instance = instance - self.instance._state.adding = False object_data = model_to_dict(instance, opts.fields, opts.exclude) # if initial was provided, it should override the values from instance if initial is not None: diff --git a/tests/regressiontests/model_regress/models.py b/tests/regressiontests/model_regress/models.py index 6d1573aea3..e4c7c3bf36 100644 --- a/tests/regressiontests/model_regress/models.py +++ b/tests/regressiontests/model_regress/models.py @@ -58,6 +58,8 @@ class BrokenUnicodeMethod(models.Model): # object). return 'Názov: %s' % self.name +class NonAutoPK(models.Model): + name = models.CharField(max_length=10, primary_key=True) __test__ = {'API_TESTS': """ (NOTE: Part of the regression test here is merely parsing the model diff --git a/tests/regressiontests/model_regress/tests.py b/tests/regressiontests/model_regress/tests.py index 0257c63d8c..6397b90a66 100644 --- a/tests/regressiontests/model_regress/tests.py +++ b/tests/regressiontests/model_regress/tests.py @@ -1,16 +1,26 @@ -from models import Worker +from django.core.exceptions import ValidationError from django.test import TestCase +from models import Worker, NonAutoPK + + class RelatedModelOrderedLookupTest(TestCase): """ Regression test for #10153: foreign key __gte and __lte lookups. """ - + # The bug is that the following queries would raise: # "TypeError: Related Field has invalid lookup: gte" - + def test_related_gte_lookup(self): Worker.objects.filter(department__gte=0) def test_related_lte_lookup(self): Worker.objects.filter(department__lte=0) + + +class ModelValidationTest(TestCase): + def test_pk_validation(self): + one = NonAutoPK.objects.create(name="one") + again = NonAutoPK(name="one") + self.assertRaises(ValidationError, again.validate_unique)