diff --git a/django/forms/models.py b/django/forms/models.py index 430dd4d7cce..96e2008e3f3 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -48,10 +48,6 @@ def construct_instance(form, instance, fields=None, exclude=None): continue if exclude and f.name in exclude: continue - # OneToOneField doesn't allow assignment of None. Guard against that - # instead of allowing it and throwing an error. - if isinstance(f, models.OneToOneField) and cleaned_data[f.name] is None: - continue # Defer saving file-type fields until after the other fields, so a # callable upload_to can use the values from other fields. if isinstance(f, models.FileField): diff --git a/tests/regressiontests/model_forms_regress/models.py b/tests/regressiontests/model_forms_regress/models.py index 23ac7452745..871bb6f815b 100644 --- a/tests/regressiontests/model_forms_regress/models.py +++ b/tests/regressiontests/model_forms_regress/models.py @@ -47,3 +47,10 @@ class RealPerson(models.Model): if self.name.lower() == 'anonymous': raise ValidationError("Please specify a real name.") +class Author(models.Model): + publication = models.OneToOneField(Publication, null=True, blank=True) + full_name = models.CharField(max_length=255) + +class Author1(models.Model): + publication = models.OneToOneField(Publication, null=False) + full_name = models.CharField(max_length=255) diff --git a/tests/regressiontests/model_forms_regress/tests.py b/tests/regressiontests/model_forms_regress/tests.py index c923a12e15e..d03e61d4fa3 100644 --- a/tests/regressiontests/model_forms_regress/tests.py +++ b/tests/regressiontests/model_forms_regress/tests.py @@ -6,7 +6,7 @@ from django.forms.models import modelform_factory from django.conf import settings from django.test import TestCase -from models import Person, RealPerson, Triple, FilePathModel, Article, Publication, CustomFF +from models import Person, RealPerson, Triple, FilePathModel, Article, Publication, CustomFF, Author, Author1 class ModelMultipleChoiceFieldTests(TestCase): @@ -152,3 +152,35 @@ class ModelClassTests(TestCase): class NoModelModelForm(forms.ModelForm): pass self.assertRaises(ValueError, NoModelModelForm) + +class OneToOneFieldTests(TestCase): + def test_assignment_of_none(self): + class AuthorForm(forms.ModelForm): + class Meta: + model = Author + fields = ['publication', 'full_name'] + + publication = Publication.objects.create(title="Pravda", + date_published=date(1991, 8, 22)) + author = Author.objects.create(publication=publication, full_name='John Doe') + form = AuthorForm({'publication':u'', 'full_name':'John Doe'}, instance=author) + self.assert_(form.is_valid()) + self.assertEqual(form.cleaned_data['publication'], None) + author = form.save() + # author object returned from form still retains original publication object + # that's why we need to retreive it from database again + new_author = Author.objects.get(pk=author.pk) + self.assertEqual(new_author.publication, None) + + def test_assignment_of_none_null_false(self): + class AuthorForm(forms.ModelForm): + class Meta: + model = Author1 + fields = ['publication', 'full_name'] + + publication = Publication.objects.create(title="Pravda", + date_published=date(1991, 8, 22)) + author = Author1.objects.create(publication=publication, full_name='John Doe') + form = AuthorForm({'publication':u'', 'full_name':'John Doe'}, instance=author) + self.assert_(not form.is_valid()) +