Loading django/contrib/contenttypes/fields.py +5 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,11 @@ class GenericForeignKey(object): if value is not None: ct = self.get_content_type(obj=value) fk = value._get_pk_val() if fk is None: raise ValueError( 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % (value, value._meta.object_name) ) setattr(instance, self.ct_field, ct) setattr(instance, self.fk_field, fk) Loading django/db/models/fields/related.py +12 −5 Original line number Diff line number Diff line Loading @@ -617,13 +617,20 @@ class ReverseSingleRelatedObjectDescriptor(object): if related is not None: setattr(related, self.field.related.get_cache_name(), None) # Set the value of the related field for lh_field, rh_field in self.field.related_fields: try: setattr(instance, lh_field.attname, getattr(value, rh_field.attname)) except AttributeError: setattr(instance, lh_field.attname, None) # Set the values of the related field. else: for lh_field, rh_field in self.field.related_fields: val = getattr(value, rh_field.attname) if val is None: raise ValueError( 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % (value, self.field.rel.to._meta.object_name) ) setattr(instance, lh_field.attname, val) # Since we already know what the related object is, seed the related # object caches now, too. This avoids another db hit if you get the # object you just set. Loading docs/releases/1.8.txt +41 −13 Original line number Diff line number Diff line Loading @@ -218,19 +218,47 @@ Backwards incompatible changes in 1.8 deprecation timeline for a given feature, its removal may appear as a backwards incompatible change. * Some operations on related objects such as Related object operations are run in a transaction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some operations on related objects such as :meth:`~django.db.models.fields.related.RelatedManager.add()` or :ref:`direct assignment<direct-assignment>` ran multiple data modifying queries without wrapping them in transactions. To reduce the risk of data corruption, all data modifying methods that affect multiple related objects (i.e. ``add()``, ``remove()``, ``clear()``, and :ref:`direct assignment<direct-assignment>`) now perform their data modifying queries from within a transaction, provided your database supports transactions. This has one backwards incompatible side effect, signal handlers triggered from these methods are now executed within the method's transaction and any exception in a signal handler will prevent the whole operation. (i.e. ``add()``, ``remove()``, ``clear()``, and :ref:`direct assignment <direct-assignment>`) now perform their data modifying queries from within a transaction, provided your database supports transactions. This has one backwards incompatible side effect, signal handlers triggered from these methods are now executed within the method's transaction and any exception in a signal handler will prevent the whole operation. Unassigning unsaved objects to relations raises an error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assigning unsaved objects to a :class:`~django.db.models.ForeignKey`, :class:`~django.contrib.contenttypes.fields.GenericForeignKey`, and :class:`~django.db.models.OneToOneField` now raises a :exc:`ValueError`. Previously, the assignment of an unsaved object would be silently ignored. For example:: >>> book = Book.objects.create(name="Django") >>> book.author = Author(name="John") >>> book.author.save() >>> book.save() >>> Book.objects.get(name="Django") >>> book.author >>> Now, an error will be raised to prevent data loss:: >>> book.author = Author(name="john") Traceback (most recent call last): ... ValueError: Cannot assign "<Author: John>": "Author" instance isn't saved in the database. Miscellaneous ~~~~~~~~~~~~~ Loading docs/topics/db/examples/many_to_one.txt +15 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,21 @@ Create an Article:: >>> a.reporter <Reporter: John Smith> Note that you must save an object before it can be assigned to a foreign key relationship. For example, creating an ``Article`` with unsaved ``Reporter`` raises ``ValueError``:: >>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com') >>> Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Reporter: John Smith>": "Reporter" instance isn't saved in the database.' .. versionchanged:: 1.8 Previously, assigning unsaved objects did not raise an error and could result in silent data loss. Article objects have access to their related Reporter objects:: >>> r = a.reporter Loading docs/topics/db/examples/one_to_one.txt +19 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,25 @@ Set the place back again, using assignment in the reverse direction:: >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> Note that you must save an object before it can be assigned to a one-to-one relationship. For example, creating an ``Restaurant`` with unsaved ``Place`` raises ``ValueError``:: >>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton') >>> Restaurant(place=p3, serves_hot_dogs=True, serves_pizza=False) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Place: Demon Dogs>": "Place" instance isn't saved in the database.' >>> p.restaurant = Restaurant(place=p, serves_hot_dogs=True, serves_pizza=False) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Restaurant: Demon Dogs the restaurant>": "Restaurant" instance isn't saved in the database.' .. versionchanged:: 1.8 Previously, assigning unsaved objects did not raise an error and could result in silent data loss. Restaurant.objects.all() just returns the Restaurants, not the Places. Note that there are two restaurants - Ace Hardware the Restaurant was created in the call to r.place = p2:: Loading Loading
django/contrib/contenttypes/fields.py +5 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,11 @@ class GenericForeignKey(object): if value is not None: ct = self.get_content_type(obj=value) fk = value._get_pk_val() if fk is None: raise ValueError( 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % (value, value._meta.object_name) ) setattr(instance, self.ct_field, ct) setattr(instance, self.fk_field, fk) Loading
django/db/models/fields/related.py +12 −5 Original line number Diff line number Diff line Loading @@ -617,13 +617,20 @@ class ReverseSingleRelatedObjectDescriptor(object): if related is not None: setattr(related, self.field.related.get_cache_name(), None) # Set the value of the related field for lh_field, rh_field in self.field.related_fields: try: setattr(instance, lh_field.attname, getattr(value, rh_field.attname)) except AttributeError: setattr(instance, lh_field.attname, None) # Set the values of the related field. else: for lh_field, rh_field in self.field.related_fields: val = getattr(value, rh_field.attname) if val is None: raise ValueError( 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % (value, self.field.rel.to._meta.object_name) ) setattr(instance, lh_field.attname, val) # Since we already know what the related object is, seed the related # object caches now, too. This avoids another db hit if you get the # object you just set. Loading
docs/releases/1.8.txt +41 −13 Original line number Diff line number Diff line Loading @@ -218,19 +218,47 @@ Backwards incompatible changes in 1.8 deprecation timeline for a given feature, its removal may appear as a backwards incompatible change. * Some operations on related objects such as Related object operations are run in a transaction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some operations on related objects such as :meth:`~django.db.models.fields.related.RelatedManager.add()` or :ref:`direct assignment<direct-assignment>` ran multiple data modifying queries without wrapping them in transactions. To reduce the risk of data corruption, all data modifying methods that affect multiple related objects (i.e. ``add()``, ``remove()``, ``clear()``, and :ref:`direct assignment<direct-assignment>`) now perform their data modifying queries from within a transaction, provided your database supports transactions. This has one backwards incompatible side effect, signal handlers triggered from these methods are now executed within the method's transaction and any exception in a signal handler will prevent the whole operation. (i.e. ``add()``, ``remove()``, ``clear()``, and :ref:`direct assignment <direct-assignment>`) now perform their data modifying queries from within a transaction, provided your database supports transactions. This has one backwards incompatible side effect, signal handlers triggered from these methods are now executed within the method's transaction and any exception in a signal handler will prevent the whole operation. Unassigning unsaved objects to relations raises an error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assigning unsaved objects to a :class:`~django.db.models.ForeignKey`, :class:`~django.contrib.contenttypes.fields.GenericForeignKey`, and :class:`~django.db.models.OneToOneField` now raises a :exc:`ValueError`. Previously, the assignment of an unsaved object would be silently ignored. For example:: >>> book = Book.objects.create(name="Django") >>> book.author = Author(name="John") >>> book.author.save() >>> book.save() >>> Book.objects.get(name="Django") >>> book.author >>> Now, an error will be raised to prevent data loss:: >>> book.author = Author(name="john") Traceback (most recent call last): ... ValueError: Cannot assign "<Author: John>": "Author" instance isn't saved in the database. Miscellaneous ~~~~~~~~~~~~~ Loading
docs/topics/db/examples/many_to_one.txt +15 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,21 @@ Create an Article:: >>> a.reporter <Reporter: John Smith> Note that you must save an object before it can be assigned to a foreign key relationship. For example, creating an ``Article`` with unsaved ``Reporter`` raises ``ValueError``:: >>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com') >>> Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Reporter: John Smith>": "Reporter" instance isn't saved in the database.' .. versionchanged:: 1.8 Previously, assigning unsaved objects did not raise an error and could result in silent data loss. Article objects have access to their related Reporter objects:: >>> r = a.reporter Loading
docs/topics/db/examples/one_to_one.txt +19 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,25 @@ Set the place back again, using assignment in the reverse direction:: >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> Note that you must save an object before it can be assigned to a one-to-one relationship. For example, creating an ``Restaurant`` with unsaved ``Place`` raises ``ValueError``:: >>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton') >>> Restaurant(place=p3, serves_hot_dogs=True, serves_pizza=False) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Place: Demon Dogs>": "Place" instance isn't saved in the database.' >>> p.restaurant = Restaurant(place=p, serves_hot_dogs=True, serves_pizza=False) Traceback (most recent call last): ... ValueError: 'Cannot assign "<Restaurant: Demon Dogs the restaurant>": "Restaurant" instance isn't saved in the database.' .. versionchanged:: 1.8 Previously, assigning unsaved objects did not raise an error and could result in silent data loss. Restaurant.objects.all() just returns the Restaurants, not the Places. Note that there are two restaurants - Ace Hardware the Restaurant was created in the call to r.place = p2:: Loading