Skip to content

Commit

Permalink
Fixed #11120 -- Corrected handling of inlines attached to inherited c…
Browse files Browse the repository at this point in the history
…lasses, broken by r10756. Thanks to George Song and Michael Strickland for the simultaneous reports.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10787 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
freakboy3742 committed May 15, 2009
1 parent bed1418 commit a00be66
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 13 deletions.
15 changes: 9 additions & 6 deletions django/forms/models.py
Expand Up @@ -617,7 +617,7 @@ def save_existing_objects(self, commit=True):
# the model instance, and sometimes the PK. Handle either.
pk_value = form.fields[pk_name].clean(raw_pk_value)
pk_value = getattr(pk_value, 'pk', pk_value)

obj = existing_objects[pk_value]
if self.can_delete:
raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
Expand Down Expand Up @@ -742,7 +742,8 @@ def save_new(self, form, commit=True):
# 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(), getattr(self.instance, self.fk.rel.field_name))
pk_value = getattr(self.instance, self.fk.rel.field_name)
setattr(obj, self.fk.get_attname(), getattr(pk_value, 'pk', pk_value))
if commit:
obj.save()
# form.save_m2m() can be called via the formset later on if commit=False
Expand All @@ -757,10 +758,12 @@ def add_fields(self, form, index):
else:
# 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))
)
kwargs = {
'label': getattr(form.fields.get(self.fk.name), 'label', capfirst(self.fk.verbose_name))
}
if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name:
kwargs['to_field'] = self.fk.rel.field_name
form.fields[self.fk.name] = InlineForeignKeyField(self.instance, **kwargs)

def get_unique_error_message(self, unique_check):
unique_check = [field for field in unique_check if field != self.fk.name]
Expand Down
10 changes: 10 additions & 0 deletions tests/regressiontests/model_formsets_regress/models.py
Expand Up @@ -7,3 +7,13 @@ class User(models.Model):
class UserSite(models.Model):
user = models.ForeignKey(User, to_field="username")
data = models.IntegerField()

class Place(models.Model):
name = models.CharField(max_length=50)

class Restaurant(Place):
pass

class Manager(models.Model):
retaurant = models.ForeignKey(Restaurant)
name = models.CharField(max_length=50)
132 changes: 125 additions & 7 deletions tests/regressiontests/model_formsets_regress/tests.py
@@ -1,24 +1,142 @@
from django.forms.models import inlineformset_factory
from django.forms.models import modelform_factory, inlineformset_factory
from django.test import TestCase

from models import User, UserSite
from models import User, UserSite, Restaurant, Manager

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"
Form = modelform_factory(User)
FormSet = inlineformset_factory(User, UserSite)
user = User.objects.create(serial=1, username='apollo13')
user.save()

# Instantiate the Form and FormSet to prove
# you can create a form with no data
form = Form()
form_set = FormSet(instance=User())

# Now create a new User and UserSite instance
data = {
'serial': u'1',
'username': u'apollo13',
'usersite_set-TOTAL_FORMS': u'1',
'usersite_set-INITIAL_FORMS': u'0',
'usersite_set-0-data': u'10',
'usersite_set-0-user': u'apollo13'
}
user = User()
form = Form(data)
if form.is_valid():
user = form.save()
else:
self.fail('Errors found on form:%s' % form_set)

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})
usersite = UserSite.objects.all().values()
self.assertEqual(usersite[0]['data'], 10)
self.assertEqual(usersite[0]['user_id'], u'apollo13')
else:
self.fail('Errors found on formset:%s' % form_set.errors)

# Now update the UserSite instance
data = {
'usersite_set-TOTAL_FORMS': u'1',
'usersite_set-INITIAL_FORMS': u'1',
'usersite_set-0-id': unicode(usersite[0]['id']),
'usersite_set-0-data': u'11',
'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()
self.assertEqual(usersite[0]['data'], 11)
self.assertEqual(usersite[0]['user_id'], u'apollo13')
else:
self.fail('Errors found on formset:%s' % form_set.errors)

# Now add a new UserSite instance
data = {
'usersite_set-TOTAL_FORMS': u'2',
'usersite_set-INITIAL_FORMS': u'1',
'usersite_set-0-id': unicode(usersite[0]['id']),
'usersite_set-0-data': u'11',
'usersite_set-0-user': u'apollo13',
'usersite_set-1-data': u'42',
'usersite_set-1-user': u'apollo13'
}
form_set = FormSet(data, instance=user)
if form_set.is_valid():
form_set.save()
usersite = UserSite.objects.all().values().order_by('user')
self.assertEqual(usersite[0]['data'], 11)
self.assertEqual(usersite[0]['user_id'], u'apollo13')
self.assertEqual(usersite[1]['data'], 42)
self.assertEqual(usersite[1]['user_id'], u'apollo13')
else:
self.fail('Errors found on formset:%s' % form_set.errors)

def test_formset_over_inherited_model(self):
"A formset over a ForeignKey with a to_field can be saved. Regression for #11120"
Form = modelform_factory(Restaurant)
FormSet = inlineformset_factory(Restaurant, Manager)

# Instantiate the Form and FormSet to prove
# you can create a form with no data
form = Form()
form_set = FormSet(instance=Restaurant())

# Now create a new Restaurant and Manager instance
data = {
'name': u"Guido's House of Pasta",
'manager_set-TOTAL_FORMS': u'1',
'manager_set-INITIAL_FORMS': u'0',
'manager_set-0-name': u'Guido Van Rossum'
}
restaurant = User()
form = Form(data)
if form.is_valid():
restaurant = form.save()
else:
self.fail('Errors found on form:%s' % form_set)

form_set = FormSet(data, instance=restaurant)
if form_set.is_valid():
form_set.save()
manager = Manager.objects.all().values()
self.assertEqual(manager[0]['name'], 'Guido Van Rossum')
else:
self.fail('Errors found on formset:%s' % form_set.errors)

# Now update the Manager instance
data = {
'manager_set-TOTAL_FORMS': u'1',
'manager_set-INITIAL_FORMS': u'1',
'manager_set-0-id': unicode(manager[0]['id']),
'manager_set-0-name': u'Terry Gilliam'
}
form_set = FormSet(data, instance=restaurant)
if form_set.is_valid():
form_set.save()
manager = Manager.objects.all().values()
self.assertEqual(manager[0]['name'], 'Terry Gilliam')
else:
self.fail('Errors found on formset:%s' % form_set.errors)

# Now add a new Manager instance
data = {
'manager_set-TOTAL_FORMS': u'2',
'manager_set-INITIAL_FORMS': u'1',
'manager_set-0-id': unicode(manager[0]['id']),
'manager_set-0-name': u'Terry Gilliam',
'manager_set-1-name': u'John Cleese'
}
form_set = FormSet(data, instance=restaurant)
if form_set.is_valid():
form_set.save()
manager = Manager.objects.all().values().order_by('name')
self.assertEqual(manager[0]['name'], 'John Cleese')
self.assertEqual(manager[1]['name'], 'Terry Gilliam')
else:
self.fail('Errors found on form:%s' % form_set.errors)
self.fail('Errors found on formset:%s' % form_set.errors)

0 comments on commit a00be66

Please sign in to comment.