Ticket #25160: 25160.diff

File 25160.diff, 4.9 KB (added by Tim Graham, 5 years ago)

initial work

  • django/db/models/base.py

    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)): 
    625625        that the "save" must be an SQL insert or update (or equivalent for
    626626        non-SQL backends), respectively. Normally, they should not be set.
    627627        """
     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
    628637        using = using or router.db_for_write(self.__class__, instance=self)
    629638        if force_insert and (force_update or update_fields):
    630639            raise ValueError("Cannot force both insert and updating in model saving.")
  • django/db/models/fields/related.py

    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): 
    514514                    raise ValueError('Cannot assign "%r": the current database router prevents this relation.' % value)
    515515
    516516        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             )
    522517
    523518        # Set the value of the related field to the value of the related object's related field
    524519        for index, field in enumerate(self.related.field.local_related_fields):
    class ReverseSingleRelatedObjectDescriptor(object): 
    685680        else:
    686681            for lh_field, rh_field in self.field.related_fields:
    687682                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                     )
    693683                setattr(instance, lh_field.attname, getattr(value, rh_field.attname))
    694684
    695685        # Since we already know what the related object is, seed the related
    class ForeignObject(RelatedField): 
    15791569    one_to_many = False
    15801570    one_to_one = False
    15811571
    1582     allow_unsaved_instance_assignment = False
    15831572    requires_unique_target = True
    15841573    related_accessor_class = ForeignRelatedObjectsDescriptor
    15851574    rel_class = ForeignObjectRel
  • tests/many_to_one/tests.py

    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): 
    566566        with self.assertRaisesMessage(ValueError,
    567567                'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
    568568                % (p, Child.parent.field.remote_field.model._meta.object_name)):
    569             Child(parent=p)
     569            Child(parent=p).save()
    570570
    571571        with self.assertRaisesMessage(ValueError,
    572572                'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
  • tests/one_to_one/tests.py

    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): 
    134134        should raise an exception.
    135135        """
    136136        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):
    140139            Restaurant.objects.create(place=place, serves_hot_dogs=True, serves_pizza=False)
    141140        bar = UndergroundBar()
    142141        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):
    146144            p.undergroundbar = bar
     145            p.save()
    147146
    148147    def test_unsaved_object_check_override(self):
    149148        """
Back to Top