Commit c4828591 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

[1.0.X] Fixed #10243, #11043 -- Corrected handling of formsets over a...

[1.0.X] Fixed #10243, #11043 -- Corrected handling of formsets over a ForeignKey that uses to_field, and by extension, fixed the admin for handling fields of that type. Thanks to apollo13 for the initial patch.

Merge of r10756 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@10758 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 17d214a9
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -675,7 +675,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)

@@ -704,7 +708,7 @@ class BaseInlineFormSet(BaseModelFormSet):

    def save_new(self, form, commit=True):
        fk_attname = self.fk.get_attname()
        kwargs = {fk_attname: self.instance.pk}
        kwargs = {fk_attname: getattr(self.instance, self.fk.rel.field_name)}
        new_obj = self.model(**kwargs)
        if fk_attname == self._pk_field.attname or self._pk_field.auto_created:
            exclude =  [self._pk_field.name]
@@ -720,6 +724,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))
            )

@@ -816,7 +821,11 @@ 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:
            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
@@ -829,7 +838,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'])
        if self.pk_field:
            return self.parent_instance.pk
+0 −0

Empty file added.

+9 −0
Original line number Diff line number Diff line
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()
+24 −0
Original line number Diff line number Diff line
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