Django FormWizard - 如何根据上一步动态创建表单集
我见过 这篇文章 并不起作用(部分原因是它已过时)。我还研究了源代码树,但无济于事(测试有帮助),但我找不到答案。我想要做的是在 form0 ('start')中获取一组数据种子,它将动态地为步骤 2 构建一个表单集。步骤 2 只是一个验证步骤。
- 'start' - 用户输入分区 (subA)、邮政编码 (12345) 和批次 csv (51,52,53)
- 'step2' - 创建动态表单 (modelformset),其中包含代表 51,52,53
- 用户点击 的 3 个表单go 并构建模型
,即
data = [ { 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '51'}
{ 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '52'}
{ 'subdivision': <subA>, 'zipcode': '12345', 'lot_number': '53'} ]
我尝试过的内容
实施解决方案时这里我只获取data=None
。这是过时的,查看源代码,我认为“正确”的方法是简单地重写 get_form_instance
方法并提供它get_cleaned_data_for_step
,但这似乎重新验证和做了比我认为需要做的更多的事情(但它不起作用)。
所以..我正在寻找两件事。
- 获取以前的表单数据的正确方法是什么?
- 我如何获取该数据并使用它来创建 n 个表单集。
FWIW 我正在使用 Django 1.4-alpha 表单集向导。
这是我所拥有的。
# 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],
})
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.
- 'start' - User enters subdivision (subA), zipcode (12345) and a csv of lots (51,52,53)
- 'step2' - A dynamic form (modelformset) is created with 3 forms representing 51,52,53
- User hits go and the models are built
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.
- What is the right way to get the previous forms data.
- How do I take that data and use it to create a n-number of formsets.
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],
})
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是我想到的......
我似乎无法让 modelForm 很好地工作,所以我将两者分开并在完成时将它们合并。它还不完美,但已经很接近了..
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..