From 14e2b1b065085c1d2d3e94ebaeefe25e12595a00 Mon Sep 17 00:00:00 2001 From: Patrik Sletmo Date: Tue, 11 Dec 2018 20:41:21 +0100 Subject: [PATCH] Fixed #29981 -- Fixed inline formsets with a OnetoOneField primary key that uses to_field. --- django/forms/models.py | 8 ++++++-- tests/model_formsets_regress/models.py | 9 +++++++++ tests/model_formsets_regress/tests.py | 12 ++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/django/forms/models.py b/django/forms/models.py index 7648d97da4..fe8a67ed2b 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -958,8 +958,12 @@ class BaseInlineFormSet(BaseModelFormSet): kwargs = { 'label': getattr(form.fields.get(name), 'label', capfirst(self.fk.verbose_name)) } - if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: - kwargs['to_field'] = self.fk.remote_field.field_name + + # The InlineForeignKeyField assumes that the foreign key relation is + # based on the parent model's pk. If this isn't the case, set to_field + # to correctly resolve the initial form value. + if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: + kwargs['to_field'] = self.fk.remote_field.field_name # If we're adding a new object, ignore a parent's auto-generated key # as it will be regenerated on the save request. diff --git a/tests/model_formsets_regress/models.py b/tests/model_formsets_regress/models.py index 29d1194bc2..d0f4532a04 100644 --- a/tests/model_formsets_regress/models.py +++ b/tests/model_formsets_regress/models.py @@ -16,6 +16,15 @@ class UserProfile(models.Model): about = models.TextField() +class UserPreferences(models.Model): + user = models.OneToOneField( + User, models.CASCADE, + to_field='username', + primary_key=True, + ) + favorite_number = models.IntegerField() + + class ProfileNetwork(models.Model): profile = models.ForeignKey(UserProfile, models.CASCADE, to_field="user") network = models.IntegerField() diff --git a/tests/model_formsets_regress/tests.py b/tests/model_formsets_regress/tests.py index fb575c2f5e..0f86bbdb06 100644 --- a/tests/model_formsets_regress/tests.py +++ b/tests/model_formsets_regress/tests.py @@ -8,8 +8,8 @@ from django.forms.utils import ErrorDict, ErrorList from django.test import TestCase from .models import ( - Host, Manager, Network, ProfileNetwork, Restaurant, User, UserProfile, - UserSite, + Host, Manager, Network, ProfileNetwork, Restaurant, User, UserPreferences, + UserProfile, UserSite, ) @@ -171,6 +171,14 @@ class InlineFormsetTests(TestCase): # Testing the inline model's relation self.assertEqual(formset[0].instance.user_id, "guido") + def test_inline_model_with_primary_to_field(self): + """An inline model with a OneToOneField with to_field & primary key.""" + FormSet = inlineformset_factory(User, UserPreferences, exclude=('is_superuser',)) + user = User.objects.create(username='guido', serial=1337) + UserPreferences.objects.create(user=user, favorite_number=10) + formset = FormSet(instance=user) + self.assertEqual(formset[0].fields['user'].initial, 'guido') + def test_inline_model_with_to_field_to_rel(self): """ #13794 --- An inline model with a to_field to a related field of a