diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index ac53515c1b..cd592d587c 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -623,13 +623,13 @@ class ReverseSingleRelatedObjectDescriptor(object): # 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: + pk = value._get_pk_val() + if pk 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) + setattr(instance, lh_field.attname, getattr(value, rh_field.attname)) # 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 diff --git a/tests/many_to_one_regress/models.py b/tests/many_to_one_regress/models.py index c94bc5e05c..f1239dbef2 100644 --- a/tests/many_to_one_regress/models.py +++ b/tests/many_to_one_regress/models.py @@ -26,7 +26,7 @@ class Third(models.Model): class Parent(models.Model): - name = models.CharField(max_length=20) + name = models.CharField(max_length=20, unique=True) bestchild = models.ForeignKey('Child', null=True, related_name='favored_by') @@ -35,6 +35,10 @@ class Child(models.Model): parent = models.ForeignKey(Parent) +class ToFieldChild(models.Model): + parent = models.ForeignKey(Parent, to_field='name') + + # Multiple paths to the same model (#7110, #7125) @python_2_unicode_compatible class Category(models.Model): diff --git a/tests/many_to_one_regress/tests.py b/tests/many_to_one_regress/tests.py index a19991fd3b..f8e4d96363 100644 --- a/tests/many_to_one_regress/tests.py +++ b/tests/many_to_one_regress/tests.py @@ -4,7 +4,7 @@ from django.db import models from django.test import TestCase from .models import ( - First, Third, Parent, Child, Category, Record, Relation, Car, Driver) + First, Third, Parent, Child, ToFieldChild, Category, Record, Relation, Car, Driver) class ManyToOneRegressionTests(TestCase): @@ -67,10 +67,15 @@ class ManyToOneRegressionTests(TestCase): # Creation using keyword argument and unsaved related instance (#8070). p = Parent() with self.assertRaisesMessage(ValueError, - 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' - % (p, Child.parent.field.rel.to._meta.object_name)): + 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' + % (p, Child.parent.field.rel.to._meta.object_name)): Child(parent=p) + with self.assertRaisesMessage(ValueError, + 'Cannot assign "%r": "%s" instance isn\'t saved in the database.' + % (p, Child.parent.field.rel.to._meta.object_name)): + ToFieldChild(parent=p) + # Creation using attname keyword argument and an id will cause the # related object to be fetched. p = Parent.objects.get(name="Parent")