I've seen this post and it's not working (in part because it's dated). I've also studied the source tree to no avail (the tests helped) but I can't find my answer. What I'm looking to do is get a seed set of data in form0 ('start') which will dynamically build a formset for step2. Step 2 is simply a verification step.
i.e.
data = [ { 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '51'}
{ 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '52'}
{ 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '53'} ]
What I've tried
When implementing the solution here I only get data=None
. This is dated and looking through the source I thought the "right" way to do this was to simply override the get_form_instance
method and feed itget_cleaned_data_for_step
, but that appears to revalidate and do a lot more stuff than what I think it needs to (and it didn't work).
So.. What I'm looking for is two things.
FWIW I am using Django 1.4-alpha formset wizard.
Here is what I have.
# urls.py
url(r'homes/bulk/$', TestWizard.as_view([('start', BulkHomeForm0),
('step2', HomeFormSet)])),
# Models.py
class Subdivision(models.Model):
name = models.CharField(max_length=64)
class Home(models.Model):
lot_number = models.CharField(max_length=16)
subdivision = models.ForeignKey(Subdivision)
zipcode = models.IntegerField(validators=[validate_zipcode], null=True)
# Forms
class BulkHomeForm0(forms.Form):
subdivision = forms.ModelChoiceField(queryset=Subdivision.objects.all(), required=True)
zipcode = USZipCodeField(required=True)
lots = forms.CharField(max_length=5000, widget=forms.Textarea()
def clean(self):
subdivision = self.cleaned_data.get('subdivision', False)
zipcode = self.cleaned_data.get('zipcode', False)
final_data = []
for item in self.cleaned_data.get('lots', "").split(",")
final_data.append({'subdivision':subdivision,
'zipcode':zipcode,
'lot_number':item})
self.cleaned_data['homes'] = final_data
class BulkHomeForm1(forms.ModelForm):
class Meta:
model = Home
HomeFormSet = modelformset_factory(Home, form=BulkHomeForm1, extra=2)
# Views.py
class TestWizard(WizardView):
storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'
def get_form(self, step=None, data=None, files=None):
form = super(TestWizard, self).get_form(step=step, data=data, files=files)
return form
def done(self, form_list, **kwargs):
return render_to_response('done.html', {
'form_data': [form.cleaned_data for form in form_list],
})
Here is what I came up with..
I couldn't seem to get a modelForm to work nicely so I kept the two separate and merged them at done
. It isn't perfect yet but it's getting close..
class BulkHomeForm1(forms.Form):
lot_number = forms.CharField(max_length=16, required=True)
street_line1 = forms.CharField(max_length=100, required=True)
floorplan = forms.ModelChoiceField(queryset=Floorplan.objects.filter(is_active=True), required=False)
start_date = forms.DateField(required=False)
temp_storage_location = tempfile.mkdtemp(dir=settings.MEDIA_ROOT, prefix="bulk_homes_")
os.chmod(temp_storage_location, 02775) # TODO FIX ME
temp_storage = FileSystemStorage(location=temp_storage_location)
class BulkHomeWizard(SessionWizardView):
file_storage = temp_storage
def get_form(self, step=None, data=None, files=None):
form = super(BulkHomeWizard, self).get_form(step=step, data=data, files=files)
if self.steps.current == 'start' and form.prefix != "step2":
# Limit the subdivisions down to the specifics
sub_qs = Subdivision.objects.filter(is_active=True)
if self.request.user.company_type == "rater":
sub_qs = sub_qs.filter(rater_orgs=self.request.user.company.id)
elif self.request.user.company_type == "eep":
sub_qs = sub_qs.filter(eep_orgs=self.request.user.company.id)
form.fields['subdivision'].queryset = sub_qs
return form
def get_context_data(self, form, **kwargs):
context = super(BulkHomeWizard, self).get_context_data(form, **kwargs)
self.template_name = 'axis/bulk_%s.html' % self.steps.current
return context
def get_form_initial(self, step):
"""This is used to seed the model set with information from the previous step"""
if step == 'step2':
log.info("Into Step 2")
data = self.get_cleaned_data_for_step('start')['homes']
return data
return self.initial_dict.get(step, {})
def done(self, form_list, **kwargs):
cleaned_data = [form.cleaned_data for form in form_list]
subdivision = cleaned_data[0].get('subdivision')
city = subdivision.city
state = subdivision.state
zipcode = cleaned_data[0].get('zipcode')
for form in cleaned_data[1]:
data = Home.objects.get_or_create(lot_number = form.get('lot_number'),
floorplan = form.get('floorplan', None),
street_line1 = form.get('street_line1', None),
subdivision = subdivision,
city = subdivision.city, state=subdivision.state,
zipcode=zipcode,
start_date = form.get('start_date', None),)
obj, created = data
obj.clean()
obj.save()
if created:
log.info("Create new Home")
return HttpResponseRedirect(reverse("subdivision_view", kwargs={'subdivision_id': subdivision.id}))