mirror of
https://github.com/django/django.git
synced 2025-07-24 13:44:32 +00:00
Fixed #25160 -- Moved unsaved model instance data loss check to Model.save()
This mostly reverts5643a3b51b
and81e1a35c36
. Thanks Carl Meyer for review.
This commit is contained in:
parent
12f91f6ebd
commit
5980b05c1f
15 changed files with 106 additions and 198 deletions
|
@ -299,13 +299,6 @@ model:
|
|||
is ``True``. This mirrors the ``for_concrete_model`` argument to
|
||||
:meth:`~django.contrib.contenttypes.models.ContentTypeManager.get_for_model`.
|
||||
|
||||
.. attribute:: GenericForeignKey.allow_unsaved_instance_assignment
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
Works analogously to :attr:`ForeignKey.allow_unsaved_instance_assignment
|
||||
<django.db.models.ForeignKey.allow_unsaved_instance_assignment>`.
|
||||
|
||||
.. admonition:: Primary key type compatibility
|
||||
|
||||
The "object_id" field doesn't have to be the same type as the
|
||||
|
|
|
@ -1383,30 +1383,6 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
|
|||
|
||||
If in doubt, leave it to its default of ``True``.
|
||||
|
||||
.. attribute:: ForeignKey.allow_unsaved_instance_assignment
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
This flag was added for backwards compatibility as older versions of
|
||||
Django always allowed assigning unsaved model instances.
|
||||
|
||||
Django prevents unsaved model instances from being assigned to a
|
||||
``ForeignKey`` field to prevent accidental data loss (unsaved foreign keys
|
||||
are silently ignored when saving a model instance).
|
||||
|
||||
If you require allowing the assignment of unsaved instances and aren't
|
||||
concerned about the data loss possibility (e.g. you never save the objects
|
||||
to the database), you can disable this check by creating a subclass of the
|
||||
field class and setting its ``allow_unsaved_instance_assignment`` attribute
|
||||
to ``True``. For example::
|
||||
|
||||
class UnsavedForeignKey(models.ForeignKey):
|
||||
# A ForeignKey which can point to an unsaved object
|
||||
allow_unsaved_instance_assignment = True
|
||||
|
||||
class Book(models.Model):
|
||||
author = UnsavedForeignKey(Author, on_delete=models.CASCADE)
|
||||
|
||||
.. _ref-manytomany:
|
||||
|
||||
``ManyToManyField``
|
||||
|
@ -1607,12 +1583,6 @@ that control how the relationship functions.
|
|||
|
||||
If in doubt, leave it to its default of ``True``.
|
||||
|
||||
.. attribute:: ManyToManyField.allow_unsaved_instance_assignment
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
Works analogously to :attr:`ForeignKey.allow_unsaved_instance_assignment`.
|
||||
|
||||
:class:`ManyToManyField` does not support :attr:`~Field.validators`.
|
||||
|
||||
:attr:`~Field.null` has no effect since there is no way to require a
|
||||
|
|
|
@ -27,3 +27,7 @@ Bugfixes
|
|||
|
||||
* Fixed the recording of squashed migrations when running the ``migrate``
|
||||
command (:ticket:`25231`).
|
||||
|
||||
* Moved the :ref:`unsaved model instance assignment data loss check
|
||||
<unsaved-model-instance-check-18>` to ``Model.save()`` to allow easier usage
|
||||
of in-memory models (:ticket:`25160`).
|
||||
|
|
|
@ -685,9 +685,23 @@ 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.
|
||||
|
||||
.. _unsaved-model-instance-check-18:
|
||||
|
||||
Assigning unsaved objects to relations raises an error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. note::
|
||||
|
||||
To more easily allow in-memory usage of models, this change was reverted in
|
||||
Django 1.8.4 and replaced with a check during ``model.save()``. For example::
|
||||
|
||||
>>> book = Book.objects.create(name="Django")
|
||||
>>> book.author = Author(name="John")
|
||||
>>> book.save()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: save() prohibited to prevent data loss due to unsaved related object 'author'.
|
||||
|
||||
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`.
|
||||
|
@ -714,8 +728,8 @@ Now, an error will be raised to prevent data loss::
|
|||
If you require allowing the assignment of unsaved instances (the old behavior)
|
||||
and aren't concerned about the data loss possibility (e.g. you never save the
|
||||
objects to the database), you can disable this check by using the
|
||||
:attr:`~django.db.models.ForeignKey.allow_unsaved_instance_assignment`
|
||||
attribute.
|
||||
``ForeignKey.allow_unsaved_instance_assignment`` attribute. (This attribute was
|
||||
removed in 1.8.4 as it's no longer relevant.)
|
||||
|
||||
Management commands that only accept positional arguments
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -55,19 +55,17 @@ 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)
|
||||
>>> Article.objects.create(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.'
|
||||
ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'.
|
||||
|
||||
If you want to disable the unsaved instance check, you can use the
|
||||
:attr:`~django.db.models.ForeignKey.allow_unsaved_instance_assignment`
|
||||
attribute.
|
||||
.. versionchanged:: 1.8.4
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
|
||||
Previously, assigning unsaved objects did not raise an error and could
|
||||
result in silent data loss.
|
||||
Previously, saving an object with unsaved related objects did not raise an
|
||||
error and could result in silent data loss. In 1.8-1.8.3, unsaved model
|
||||
instances couldn't be assigned to related fields, but this restriction was
|
||||
removed to allow easier usage of in-memory models.
|
||||
|
||||
Article objects have access to their related Reporter objects::
|
||||
|
||||
|
|
|
@ -96,23 +96,17 @@ 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)
|
||||
>>> Restaurant.objects.create(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.'
|
||||
ValueError: save() prohibited to prevent data loss due to unsaved related object 'place'.
|
||||
|
||||
If you want to disable the unsaved instance check, you can use the
|
||||
:attr:`~django.db.models.ForeignKey.allow_unsaved_instance_assignment`
|
||||
attribute.
|
||||
.. versionchanged:: 1.8.4
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
|
||||
Previously, assigning unsaved objects did not raise an error and could
|
||||
result in silent data loss.
|
||||
Previously, saving an object with unsaved related objects did not raise an
|
||||
error and could result in silent data loss. In 1.8-1.8.3, unsaved model
|
||||
instances couldn't be assigned to related fields, but this restriction was
|
||||
removed to allow easier usage of in-memory models.
|
||||
|
||||
Restaurant.objects.all() just returns the Restaurants, not the Places. Note
|
||||
that there are two restaurants - Ace Hardware the Restaurant was created in the
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue