diff --git a/django/db/models/base.py b/django/db/models/base.py
index b679d08..a4aa477 100644
|
a
|
b
|
class Model(six.with_metaclass(ModelBase)):
|
| 625 | 625 | that the "save" must be an SQL insert or update (or equivalent for |
| 626 | 626 | non-SQL backends), respectively. Normally, they should not be set. |
| 627 | 627 | """ |
| | 628 | for field in self._meta.concrete_fields + self._meta.related_objects: |
| | 629 | if field.is_relation: |
| | 630 | obj = getattr(self, field.name, None) |
| | 631 | if obj and obj._state.adding: |
| | 632 | raise ValueError( |
| | 633 | "save() prohibited to prevent data loss due to " |
| | 634 | "unsaved related object '%s'." % field.name |
| | 635 | ) |
| | 636 | |
| 628 | 637 | using = using or router.db_for_write(self.__class__, instance=self) |
| 629 | 638 | if force_insert and (force_update or update_fields): |
| 630 | 639 | raise ValueError("Cannot force both insert and updating in model saving.") |
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index b038fdf..77a79d4 100644
|
a
|
b
|
class SingleRelatedObjectDescriptor(object):
|
| 514 | 514 | raise ValueError('Cannot assign "%r": the current database router prevents this relation.' % value) |
| 515 | 515 | |
| 516 | 516 | related_pk = tuple(getattr(instance, field.attname) for field in self.related.field.foreign_related_fields) |
| 517 | | if not self.related.field.allow_unsaved_instance_assignment and None in related_pk: |
| 518 | | raise ValueError( |
| 519 | | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % |
| 520 | | (value, instance._meta.object_name) |
| 521 | | ) |
| 522 | 517 | |
| 523 | 518 | # Set the value of the related field to the value of the related object's related field |
| 524 | 519 | for index, field in enumerate(self.related.field.local_related_fields): |
| … |
… |
class ReverseSingleRelatedObjectDescriptor(object):
|
| 685 | 680 | else: |
| 686 | 681 | for lh_field, rh_field in self.field.related_fields: |
| 687 | 682 | pk = value._get_pk_val() |
| 688 | | if not self.field.allow_unsaved_instance_assignment and pk is None: |
| 689 | | raise ValueError( |
| 690 | | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' % |
| 691 | | (value, self.field.remote_field.model._meta.object_name) |
| 692 | | ) |
| 693 | 683 | setattr(instance, lh_field.attname, getattr(value, rh_field.attname)) |
| 694 | 684 | |
| 695 | 685 | # Since we already know what the related object is, seed the related |
| … |
… |
class ForeignObject(RelatedField):
|
| 1579 | 1569 | one_to_many = False |
| 1580 | 1570 | one_to_one = False |
| 1581 | 1571 | |
| 1582 | | allow_unsaved_instance_assignment = False |
| 1583 | 1572 | requires_unique_target = True |
| 1584 | 1573 | related_accessor_class = ForeignRelatedObjectsDescriptor |
| 1585 | 1574 | rel_class = ForeignObjectRel |
diff --git a/tests/many_to_one/tests.py b/tests/many_to_one/tests.py
index d828abe..c1222ce 100644
|
a
|
b
|
class ManyToOneTests(TestCase):
|
| 566 | 566 | with self.assertRaisesMessage(ValueError, |
| 567 | 567 | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' |
| 568 | 568 | % (p, Child.parent.field.remote_field.model._meta.object_name)): |
| 569 | | Child(parent=p) |
| | 569 | Child(parent=p).save() |
| 570 | 570 | |
| 571 | 571 | with self.assertRaisesMessage(ValueError, |
| 572 | 572 | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' |
diff --git a/tests/one_to_one/tests.py b/tests/one_to_one/tests.py
index 041fe68..01a489d 100644
|
a
|
b
|
class OneToOneTests(TestCase):
|
| 134 | 134 | should raise an exception. |
| 135 | 135 | """ |
| 136 | 136 | place = Place(name='User', address='London') |
| 137 | | with self.assertRaisesMessage(ValueError, |
| 138 | | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' |
| 139 | | % (place, Restaurant.place.field.remote_field.model._meta.object_name)): |
| | 137 | msg = "save() prohibited to prevent data loss due to unsaved related object 'place'." |
| | 138 | with self.assertRaisesMessage(ValueError, msg): |
| 140 | 139 | Restaurant.objects.create(place=place, serves_hot_dogs=True, serves_pizza=False) |
| 141 | 140 | bar = UndergroundBar() |
| 142 | 141 | p = Place(name='User', address='London') |
| 143 | | with self.assertRaisesMessage(ValueError, |
| 144 | | 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' |
| 145 | | % (bar, p._meta.object_name)): |
| | 142 | msg = "save() prohibited to prevent data loss due to unsaved related object 'undergroundbar'." |
| | 143 | with self.assertRaisesMessage(ValueError, msg): |
| 146 | 144 | p.undergroundbar = bar |
| | 145 | p.save() |
| 147 | 146 | |
| 148 | 147 | def test_unsaved_object_check_override(self): |
| 149 | 148 | """ |