Skip to content

Commit

Permalink
Fixed #17677 -- Made sure the WizardView doesn't accidentally overwri…
Browse files Browse the repository at this point in the history
…te 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
  • Loading branch information
jezdez committed Mar 4, 2012
1 parent 60a62bf commit 59a436e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 4 deletions.
1 change: 1 addition & 0 deletions django/contrib/formtools/tests/wizard/__init__.py
Expand Up @@ -15,4 +15,5 @@
CookieWizardTests,
WizardTestKwargs,
WizardTestGenericViewInterface,
WizardFormKwargsOverrideTests,
)
9 changes: 9 additions & 0 deletions django/contrib/formtools/tests/wizard/wizardtests/forms.py
Expand Up @@ -2,8 +2,10 @@
import tempfile

from django import forms
from django.contrib.auth.models import User
from django.core.files.storage import FileSystemStorage
from django.forms.formsets import formset_factory
from django.forms.models import modelformset_factory
from django.http import HttpResponse
from django.template import Template, Context

Expand Down Expand Up @@ -50,6 +52,13 @@ def get_context_data(self, form, **kwargs):
context.update({'another_var': True})
return context

class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email')

UserFormSet = modelformset_factory(User, form=UserForm)

class SessionContactWizard(ContactWizard):
storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'

Expand Down
46 changes: 46 additions & 0 deletions django/contrib/formtools/tests/wizard/wizardtests/tests.py
Expand Up @@ -7,6 +7,7 @@
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.formtools.wizard.views import CookieWizardView
from django.contrib.formtools.tests.wizard.forms import UserForm, UserFormSet


class WizardTests(object):
Expand Down Expand Up @@ -331,3 +332,48 @@ def get_context_data(self, **kwargs):
response = view(factory.get('/'))
self.assertEquals(response.context_data['test_key'], 'test_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)))
10 changes: 6 additions & 4 deletions django/contrib/formtools/wizard/views.py
Expand Up @@ -385,11 +385,13 @@ def get_form(self, step=None, data=None, files=None):
'initial': self.get_form_initial(step),
})
if issubclass(self.form_list[step], forms.ModelForm):
# If the form is based on ModelForm, add instance if available.
kwargs.update({'instance': self.get_form_instance(step)})
# If the form is based on ModelForm, add instance if available
# and not previously set.
kwargs.setdefault('instance', self.get_form_instance(step))
elif issubclass(self.form_list[step], forms.models.BaseModelFormSet):
# If the form is based on ModelFormSet, add queryset if available.
kwargs.update({'queryset': self.get_form_instance(step)})
# If the form is based on ModelFormSet, add queryset if available
# and not previous set.
kwargs.setdefault('queryset', self.get_form_instance(step))
return self.form_list[step](**kwargs)

def process_step(self, form):
Expand Down

0 comments on commit 59a436e

Please sign in to comment.