Fixed #17677 -- Made sure the WizardView doesn't accidentally overwrite the `instance` or `queryset` form parameters when they are already set by the `get_form_kwargs` method. Thanks to goodtune and Stephan Jäkel.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17651 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2012-03-04 16:10:18 +00:00
parent 60a62bf6f2
commit 59a436e963
4 changed files with 62 additions and 4 deletions

View File

@ -15,4 +15,5 @@ from django.contrib.formtools.tests.wizard.wizardtests.tests import (
CookieWizardTests, CookieWizardTests,
WizardTestKwargs, WizardTestKwargs,
WizardTestGenericViewInterface, WizardTestGenericViewInterface,
WizardFormKwargsOverrideTests,
) )

View File

@ -2,8 +2,10 @@ import os
import tempfile import tempfile
from django import forms from django import forms
from django.contrib.auth.models import User
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.forms.formsets import formset_factory from django.forms.formsets import formset_factory
from django.forms.models import modelformset_factory
from django.http import HttpResponse from django.http import HttpResponse
from django.template import Template, Context from django.template import Template, Context
@ -50,6 +52,13 @@ class ContactWizard(WizardView):
context.update({'another_var': True}) context.update({'another_var': True})
return context return context
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email')
UserFormSet = modelformset_factory(User, form=UserForm)
class SessionContactWizard(ContactWizard): class SessionContactWizard(ContactWizard):
storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'

View File

@ -7,6 +7,7 @@ from django.test.client import RequestFactory
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.formtools.wizard.views import CookieWizardView from django.contrib.formtools.wizard.views import CookieWizardView
from django.contrib.formtools.tests.wizard.forms import UserForm, UserFormSet
class WizardTests(object): class WizardTests(object):
@ -331,3 +332,48 @@ class WizardTestGenericViewInterface(TestCase):
response = view(factory.get('/')) response = view(factory.get('/'))
self.assertEquals(response.context_data['test_key'], 'test_value') self.assertEquals(response.context_data['test_key'], 'test_value')
self.assertEquals(response.context_data['another_key'], 'another_value') self.assertEquals(response.context_data['another_key'], 'another_value')
class WizardFormKwargsOverrideTests(TestCase):
def setUp(self):
super(WizardFormKwargsOverrideTests, self).setUp()
self.rf = RequestFactory()
# Create two users so we can filter by is_staff when handing our
# wizard a queryset keyword argument.
self.normal_user = User.objects.create(username='test1', email='normal@example.com')
self.staff_user = User.objects.create(username='test2', email='staff@example.com', is_staff=True)
def test_instance_is_maintained(self):
self.assertEqual(2, User.objects.count())
queryset = User.objects.get(pk=self.staff_user.pk)
class InstanceOverrideWizard(CookieWizardView):
def get_form_kwargs(self, step):
return {'instance': queryset}
view = InstanceOverrideWizard.as_view([UserForm])
response = view(self.rf.get('/'))
form = response.context_data['wizard']['form']
self.assertNotEqual(form.instance.pk, None)
self.assertEqual(form.instance.pk, self.staff_user.pk)
self.assertEqual('staff@example.com', form.initial.get('email', None))
def test_queryset_is_maintained(self):
queryset = User.objects.filter(pk=self.staff_user.pk)
class QuerySetOverrideWizard(CookieWizardView):
def get_form_kwargs(self, step):
return {'queryset': queryset}
view = QuerySetOverrideWizard.as_view([UserFormSet])
response = view(self.rf.get('/'))
formset = response.context_data['wizard']['form']
self.assertNotEqual(formset.queryset, None)
self.assertEqual(formset.initial_form_count(), 1)
self.assertEqual(['staff@example.com'],
list(formset.queryset.values_list('email', flat=True)))

View File

@ -385,11 +385,13 @@ class WizardView(TemplateView):
'initial': self.get_form_initial(step), 'initial': self.get_form_initial(step),
}) })
if issubclass(self.form_list[step], forms.ModelForm): if issubclass(self.form_list[step], forms.ModelForm):
# If the form is based on ModelForm, add instance if available. # If the form is based on ModelForm, add instance if available
kwargs.update({'instance': self.get_form_instance(step)}) # and not previously set.
kwargs.setdefault('instance', self.get_form_instance(step))
elif issubclass(self.form_list[step], forms.models.BaseModelFormSet): elif issubclass(self.form_list[step], forms.models.BaseModelFormSet):
# If the form is based on ModelFormSet, add queryset if available. # If the form is based on ModelFormSet, add queryset if available
kwargs.update({'queryset': self.get_form_instance(step)}) # and not previous set.
kwargs.setdefault('queryset', self.get_form_instance(step))
return self.form_list[step](**kwargs) return self.form_list[step](**kwargs)
def process_step(self, form): def process_step(self, form):