Author: russellm
Date: 2009-05-13 09:32:18 -0500 (Wed, 13 May 2009)
New Revision: 10758

Added:
   django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/
   
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/__init__.py
   
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/models.py
   
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/tests.py
Modified:
   django/branches/releases/1.0.X/django/forms/models.py
Log:
[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.

Modified: django/branches/releases/1.0.X/django/forms/models.py
===================================================================
--- django/branches/releases/1.0.X/django/forms/models.py       2009-05-13 
14:31:39 UTC (rev 10757)
+++ django/branches/releases/1.0.X/django/forms/models.py       2009-05-13 
14:32:18 UTC (rev 10758)
@@ -464,7 +464,7 @@
             #
             # This logic is in the wrong place here on the 1.0.X branch.
             # In the 1.1 series this logic exists as the QuerySet.ordered
-            # property, but since that's new in 1.1 here in 1.0 we just 
+            # property, but since that's new in 1.1 here in 1.0 we just
             # have to deal with this slightly smelly code here.
             if qs.query.extra_order_by or qs.query.order_by:
                 ordered = True
@@ -675,7 +675,11 @@
         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 @@
 
     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 @@
             # 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,8 +821,12 @@
     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)
@@ -829,7 +838,11 @@
             # 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

Added: 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/__init__.py
===================================================================

Added: 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/models.py
===================================================================
--- 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/models.py
                               (rev 0)
+++ 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/models.py
       2009-05-13 14:32:18 UTC (rev 10758)
@@ -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()

Added: 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/tests.py
===================================================================
--- 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/tests.py
                                (rev 0)
+++ 
django/branches/releases/1.0.X/tests/regressiontests/model_formsets_regress/tests.py
        2009-05-13 14:32:18 UTC (rev 10758)
@@ -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


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to