diff --git a/django/db/models/base.py b/django/db/models/base.py index f29d7db629..27117742eb 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -263,7 +263,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 2c679b04a6..b150d0cce1 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -282,6 +282,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]) @@ -1220,6 +1222,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 @@ -1475,6 +1478,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 c5be8aa1e3..6ba2bed472 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -244,10 +244,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 420f2c262c..6c5d7bd59e 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)