summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/forms/models.py21
-rw-r--r--tests/regressiontests/model_formsets_regress/__init__.py0
-rw-r--r--tests/regressiontests/model_formsets_regress/models.py9
-rw-r--r--tests/regressiontests/model_formsets_regress/tests.py24
4 files changed, 50 insertions, 4 deletions
diff --git a/django/forms/models.py b/django/forms/models.py
index d42b98483b..705ef10f17 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -698,7 +698,11 @@ class BaseInlineFormSet(BaseModelFormSet):
self.save_as_new = save_as_new
# is there a better way to get the object descriptor?
self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
- qs = self.model._default_manager.filter(**{self.fk.name: self.instance})
+ if self.fk.rel.field_name == self.fk.rel.to._meta.pk.name:
+ backlink_value = self.instance
+ else:
+ backlink_value = getattr(self.instance, self.fk.rel.field_name)
+ qs = self.model._default_manager.filter(**{self.fk.name: backlink_value})
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
queryset=qs)
@@ -733,7 +737,7 @@ class BaseInlineFormSet(BaseModelFormSet):
# Use commit=False so we can assign the parent key afterwards, then
# save the object.
obj = form.save(commit=False)
- setattr(obj, self.fk.get_attname(), self.instance.pk)
+ setattr(obj, self.fk.get_attname(), getattr(self.instance, self.fk.rel.field_name))
if commit:
obj.save()
# form.save_m2m() can be called via the formset later on if commit=False
@@ -749,6 +753,7 @@ class BaseInlineFormSet(BaseModelFormSet):
# The foreign key field might not be on the form, so we poke at the
# Model field to get the label, since we need that for error messages.
form.fields[self.fk.name] = InlineForeignKeyField(self.instance,
+ to_field=self.fk.rel.field_name,
label=getattr(form.fields.get(self.fk.name), 'label', capfirst(self.fk.verbose_name))
)
@@ -845,8 +850,12 @@ class InlineForeignKeyField(Field):
def __init__(self, parent_instance, *args, **kwargs):
self.parent_instance = parent_instance
self.pk_field = kwargs.pop("pk_field", False)
+ self.to_field = kwargs.pop("to_field", None)
if self.parent_instance is not None:
- kwargs["initial"] = self.parent_instance.pk
+ if self.to_field:
+ kwargs["initial"] = getattr(self.parent_instance, self.to_field)
+ else:
+ kwargs["initial"] = self.parent_instance.pk
kwargs["required"] = False
kwargs["widget"] = InlineForeignKeyHiddenInput
super(InlineForeignKeyField, self).__init__(*args, **kwargs)
@@ -858,7 +867,11 @@ class InlineForeignKeyField(Field):
# if there is no value act as we did before.
return self.parent_instance
# ensure the we compare the values as equal types.
- if force_unicode(value) != force_unicode(self.parent_instance.pk):
+ if self.to_field:
+ orig = getattr(self.parent_instance, self.to_field)
+ else:
+ orig = self.parent_instance.pk
+ if force_unicode(value) != force_unicode(orig):
raise ValidationError(self.error_messages['invalid_choice'])
return self.parent_instance
diff --git a/tests/regressiontests/model_formsets_regress/__init__.py b/tests/regressiontests/model_formsets_regress/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/model_formsets_regress/__init__.py
diff --git a/tests/regressiontests/model_formsets_regress/models.py b/tests/regressiontests/model_formsets_regress/models.py
new file mode 100644
index 0000000000..51fc6a49ab
--- /dev/null
+++ b/tests/regressiontests/model_formsets_regress/models.py
@@ -0,0 +1,9 @@
+from django.db import models
+
+class User(models.Model):
+ username = models.CharField(max_length=12, unique=True)
+ serial = models.IntegerField()
+
+class UserSite(models.Model):
+ user = models.ForeignKey(User, to_field="username")
+ data = models.IntegerField()
diff --git a/tests/regressiontests/model_formsets_regress/tests.py b/tests/regressiontests/model_formsets_regress/tests.py
new file mode 100644
index 0000000000..c20c1f4077
--- /dev/null
+++ b/tests/regressiontests/model_formsets_regress/tests.py
@@ -0,0 +1,24 @@
+from django.forms.models import inlineformset_factory
+from django.test import TestCase
+
+from models import User, UserSite
+
+class InlineFormsetTests(TestCase):
+ def test_formset_over_to_field(self):
+ "A formset over a ForeignKey with a to_field can be saved. Regression for #10243"
+ FormSet = inlineformset_factory(User, UserSite)
+ user = User.objects.create(serial=1, username='apollo13')
+ user.save()
+ data = {
+ 'usersite_set-TOTAL_FORMS': u'1',
+ 'usersite_set-INITIAL_FORMS': u'0',
+ 'usersite_set-0-data': u'10',
+ 'usersite_set-0-user': u'apollo13'
+ }
+ form_set = FormSet(data, instance=user)
+ if form_set.is_valid():
+ form_set.save()
+ usersite = UserSite.objects.all().values()[0]
+ self.assertEqual(usersite, {'data': 10, 'user_id': u'apollo13', 'id': 1})
+ else:
+ self.fail('Errors found on form:%s' % form_set.errors) \ No newline at end of file