Loading django/db/models/fields/related_descriptors.py +10 −25 Original line number Diff line number Diff line Loading @@ -193,14 +193,8 @@ class ForwardManyToOneDescriptor(object): - ``instance`` is the ``child`` instance - ``value`` in the ``parent`` instance on the right of the equal sign """ # If null=True, we can assign null here, but otherwise the value needs # to be an instance of the related class. if value is None and self.field.null is False: raise ValueError( 'Cannot assign None: "%s.%s" does not allow null values.' % (instance._meta.object_name, self.field.name) ) elif value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model): # An object must be an instance of the related class. if value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model): raise ValueError( 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % ( value, Loading Loading @@ -379,10 +373,7 @@ class ReverseOneToOneDescriptor(object): # ForwardManyToOneDescriptor is annoying, but there's a bunch # of small differences that would make a common base class convoluted. # If null=True, we can assign null here, but otherwise the value needs # to be an instance of the related class. if value is None: if self.related.field.null: # Update the cached related instance (if any) & clear the cache. try: rel_obj = getattr(instance, self.cache_name) Loading @@ -391,14 +382,8 @@ class ReverseOneToOneDescriptor(object): else: delattr(instance, self.cache_name) setattr(rel_obj, self.related.field.name, None) else: raise ValueError( 'Cannot assign None: "%s.%s" does not allow null values.' % ( instance._meta.object_name, self.related.get_accessor_name(), ) ) elif not isinstance(value, self.related.related_model): # An object must be an instance of the related class. raise ValueError( 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % ( value, Loading docs/releases/1.10.txt +8 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,14 @@ creates the possibility of a deadlock. To adapt your code in the case of RQ, you can `provide your own worker script <http://python-rq.org/docs/workers/>`_ that calls ``django.setup()``. Removed null assignment check for non-null foreign key fields ------------------------------------------------------------- In older versions, assigning ``None`` to a non-nullable ``ForeignKey`` or ``OneToOneField`` raised ``ValueError('Cannot assign None: "model.field" does not allow null values.')``. For consistency with other model fields which don't have a similar check, this check is removed. Miscellaneous ------------- Loading tests/generic_relations/tests.py +3 −6 Original line number Diff line number Diff line Loading @@ -717,14 +717,11 @@ class ProxyRelatedModelTest(TestCase): class TestInitWithNoneArgument(SimpleTestCase): def test_none_not_allowed(self): # TaggedItem requires a content_type, initializing with None should # raise a ValueError. msg = 'Cannot assign None: "TaggedItem.content_type" does not allow null values' with self.assertRaisesMessage(ValueError, msg): TaggedItem(content_object=None) def test_none_allowed(self): # AllowsNullGFK doesn't require a content_type, so None argument should # also be allowed. AllowsNullGFK(content_object=None) # TaggedItem requires a content_type but initializing with None should # be allowed. TaggedItem(content_object=None) tests/many_to_one/tests.py +9 −8 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from copy import deepcopy from django.core.exceptions import FieldError, MultipleObjectsReturned from django.db import models, transaction from django.db.utils import IntegrityError from django.test import TestCase from django.utils import six from django.utils.deprecation import RemovedInDjango20Warning Loading Loading @@ -486,19 +487,19 @@ class ManyToOneTests(TestCase): p = Parent.objects.get(name="Parent") self.assertIsNone(p.bestchild) # Assigning None fails: Child.parent is null=False. with self.assertRaises(ValueError): # Assigning None will not fail: Child.parent is null=False. setattr(c, "parent", None) # You also can't assign an object of the wrong type here with self.assertRaises(ValueError): setattr(c, "parent", First(id=1, second=1)) # Nor can you explicitly assign None to Child.parent during object # creation (regression for #9649). with self.assertRaises(ValueError): # You can assign None to Child.parent during object creation. Child(name='xyzzy', parent=None) with self.assertRaises(ValueError): # But when trying to save a Child with parent=None, the database will # raise IntegrityError. with self.assertRaises(IntegrityError), transaction.atomic(): Child.objects.create(name='xyzzy', parent=None) # Creation using keyword argument should cache the related object. Loading tests/one_to_one/tests.py +2 −3 Original line number Diff line number Diff line Loading @@ -228,8 +228,7 @@ class OneToOneTests(TestCase): ug_bar.place = None self.assertIsNone(ug_bar.place) # Assigning None fails: Place.restaurant is null=False with self.assertRaises(ValueError): # Assigning None will not fail: Place.restaurant is null=False setattr(p, 'restaurant', None) # You also can't assign an object of the wrong type here Loading Loading
django/db/models/fields/related_descriptors.py +10 −25 Original line number Diff line number Diff line Loading @@ -193,14 +193,8 @@ class ForwardManyToOneDescriptor(object): - ``instance`` is the ``child`` instance - ``value`` in the ``parent`` instance on the right of the equal sign """ # If null=True, we can assign null here, but otherwise the value needs # to be an instance of the related class. if value is None and self.field.null is False: raise ValueError( 'Cannot assign None: "%s.%s" does not allow null values.' % (instance._meta.object_name, self.field.name) ) elif value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model): # An object must be an instance of the related class. if value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model): raise ValueError( 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % ( value, Loading Loading @@ -379,10 +373,7 @@ class ReverseOneToOneDescriptor(object): # ForwardManyToOneDescriptor is annoying, but there's a bunch # of small differences that would make a common base class convoluted. # If null=True, we can assign null here, but otherwise the value needs # to be an instance of the related class. if value is None: if self.related.field.null: # Update the cached related instance (if any) & clear the cache. try: rel_obj = getattr(instance, self.cache_name) Loading @@ -391,14 +382,8 @@ class ReverseOneToOneDescriptor(object): else: delattr(instance, self.cache_name) setattr(rel_obj, self.related.field.name, None) else: raise ValueError( 'Cannot assign None: "%s.%s" does not allow null values.' % ( instance._meta.object_name, self.related.get_accessor_name(), ) ) elif not isinstance(value, self.related.related_model): # An object must be an instance of the related class. raise ValueError( 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % ( value, Loading
docs/releases/1.10.txt +8 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,14 @@ creates the possibility of a deadlock. To adapt your code in the case of RQ, you can `provide your own worker script <http://python-rq.org/docs/workers/>`_ that calls ``django.setup()``. Removed null assignment check for non-null foreign key fields ------------------------------------------------------------- In older versions, assigning ``None`` to a non-nullable ``ForeignKey`` or ``OneToOneField`` raised ``ValueError('Cannot assign None: "model.field" does not allow null values.')``. For consistency with other model fields which don't have a similar check, this check is removed. Miscellaneous ------------- Loading
tests/generic_relations/tests.py +3 −6 Original line number Diff line number Diff line Loading @@ -717,14 +717,11 @@ class ProxyRelatedModelTest(TestCase): class TestInitWithNoneArgument(SimpleTestCase): def test_none_not_allowed(self): # TaggedItem requires a content_type, initializing with None should # raise a ValueError. msg = 'Cannot assign None: "TaggedItem.content_type" does not allow null values' with self.assertRaisesMessage(ValueError, msg): TaggedItem(content_object=None) def test_none_allowed(self): # AllowsNullGFK doesn't require a content_type, so None argument should # also be allowed. AllowsNullGFK(content_object=None) # TaggedItem requires a content_type but initializing with None should # be allowed. TaggedItem(content_object=None)
tests/many_to_one/tests.py +9 −8 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from copy import deepcopy from django.core.exceptions import FieldError, MultipleObjectsReturned from django.db import models, transaction from django.db.utils import IntegrityError from django.test import TestCase from django.utils import six from django.utils.deprecation import RemovedInDjango20Warning Loading Loading @@ -486,19 +487,19 @@ class ManyToOneTests(TestCase): p = Parent.objects.get(name="Parent") self.assertIsNone(p.bestchild) # Assigning None fails: Child.parent is null=False. with self.assertRaises(ValueError): # Assigning None will not fail: Child.parent is null=False. setattr(c, "parent", None) # You also can't assign an object of the wrong type here with self.assertRaises(ValueError): setattr(c, "parent", First(id=1, second=1)) # Nor can you explicitly assign None to Child.parent during object # creation (regression for #9649). with self.assertRaises(ValueError): # You can assign None to Child.parent during object creation. Child(name='xyzzy', parent=None) with self.assertRaises(ValueError): # But when trying to save a Child with parent=None, the database will # raise IntegrityError. with self.assertRaises(IntegrityError), transaction.atomic(): Child.objects.create(name='xyzzy', parent=None) # Creation using keyword argument should cache the related object. Loading
tests/one_to_one/tests.py +2 −3 Original line number Diff line number Diff line Loading @@ -228,8 +228,7 @@ class OneToOneTests(TestCase): ug_bar.place = None self.assertIsNone(ug_bar.place) # Assigning None fails: Place.restaurant is null=False with self.assertRaises(ValueError): # Assigning None will not fail: Place.restaurant is null=False setattr(p, 'restaurant', None) # You also can't assign an object of the wrong type here Loading