diff --git a/AUTHORS b/AUTHORS index b417f8d676..8b702fa2a4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -305,6 +305,7 @@ answer newbie questions, and generally made Django that much better: Gasper Koren Gasper Zejn Gavin Wahl + Ge Hanbin geber@datacollect.com Geert Vanderkelen George Karpenkov diff --git a/django/db/models/base.py b/django/db/models/base.py index 0d704684f1..71d04244e0 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -678,28 +678,29 @@ class Model(metaclass=ModelBase): # been assigned and there's no need to worry about this check. if field.is_relation and field.is_cached(self): obj = getattr(self, field.name, None) + if not obj: + continue # A pk may have been assigned manually to a model instance not # saved to the database (or auto-generated in a case like # UUIDField), but we allow the save to proceed and rely on the # database to raise an IntegrityError if applicable. If # constraints aren't supported by the database, there's the # unavoidable risk of data corruption. - if obj: - if obj.pk is None: - # Remove the object from a related instance cache. - if not field.remote_field.multiple: - field.remote_field.delete_cached_value(obj) - raise ValueError( - "save() prohibited to prevent data loss due to " - "unsaved related object '%s'." % field.name - ) - elif getattr(self, field.attname) is None: - # Use pk from related object if it has been saved after - # an assignment. - setattr(self, field.attname, obj.pk) + if obj.pk is None: + # Remove the object from a related instance cache. + if not field.remote_field.multiple: + field.remote_field.delete_cached_value(obj) + raise ValueError( + "save() prohibited to prevent data loss due to " + "unsaved related object '%s'." % field.name + ) + elif getattr(self, field.attname) is None: + # Use pk from related object if it has been saved after + # an assignment. + setattr(self, field.attname, obj.pk) # If the relationship's pk/to_field was changed, clear the # cached relationship. - if obj and getattr(obj, field.target_field.attname) != getattr(self, field.attname): + if getattr(obj, field.target_field.attname) != getattr(self, field.attname): field.delete_cached_value(self) using = using or router.db_for_write(self.__class__, instance=self)