我想实现一个简单的2部分FormWizard。 表单1将动态生成如下内容:
class BuyAppleForm(forms.Form):
creditcard = forms.ChoiceField(widget = forms.RadioSelect)
type = forms.ChoiceField(widget = forms.RadioSelect)
def __init__(self,*args, **kwargs):
user = kwargs['user']
del kwargs['user']
super(BuyAppleForm, self).__init__(*args, **kwargs)
credit_cards = get_credit_cards(user)
self.fields['creditcard'].choices = [(card.id,str(card)) for card in credit_cards]
apple_types= get_types_packages()
self.fields['type'].choices = [(type.id,str(type)) for type in apple_types]
这将动态创建一个包含可用选项列表的表单。
我的第二种形式,我实际上不想输入。我只想显示一个确认屏幕,其中包含信用卡信息,苹果信息和金额(总金额,税金,运费)。用户单击“确定”后,我希望开始购买苹果。
我能够通过传入kwargs中的request.user对象来实现单一表单方式。但是,使用FormWizard,我无法理解这一点。
我是否接近问题并且FormWizard不是正确的方法吗?如果是,表单__init__
方法如何从HTTP请求访问用户对象?
答案 0 :(得分:4)
我没有使用它,但对于你描述的情况,似乎你可能想尝试FormPreview而不是FormWizard。从文档中,它听起来像你正在追求的。
答案 1 :(得分:4)
当我试图弄清楚FormWizard的时候,我搜遍了所有的回答,发现大多数这些只是说不要使用它的回复。 FormPreview可以正常工作,因为OP只对单级表单感兴趣,但问题仍然是如何使用FormWizard。
尽管这个问题已经过时了,但我认为回答这个问题很有价值,因为这个问题在很多网站上被提出,我看不到对它的回应,也没有明确的解决方案。
我认为就OP问题而言,重写process_step是可行的方法。诀窍是在此方法中创建将从第一种形式接收数据的表单(或视图)。
我将这个form_setup作为实用程序包装器(想象构造函数)添加到我的forms.py中:
def form_setup(**kwargs):
def makeform(data, prefix=None, initial=None):
form = FormLev2(data, prefix, initial)
for k, v in kwargs.items():
if k == 'some_list':
form.fields['some_list'].choices = v
...
return form
return makeform
然后按如下方式覆盖process_step:
def process_step(self, request, process, step):
if step == 1
if form.is_valid(): #form from step 1
objs = Table.objects.filter(...) #based on last form
self.form_list[1] = form_setup(some_list=[(o.id,o.name) for o in objs]) #(*)
...
这样,您可以动态修改form_list(*),即修改FormWizard实例中的form_list,而不是表单定义本身。包装函数对于此功能至关重要,因为它返回一个函数,该函数将实例化一个新的Form对象,然后在FormWizard中使用该函数调用下一个表单的数据,并允许您使用前一个表单中的数据。
编辑:对于Erik的评论,并澄清最后一部分。
另请注意,在步骤n之后将使用步骤[0,n]调用process_step。
答案 2 :(得分:0)
我不知道在StackOverflow上回答一个人自己的问题是否是可接受的行为,这是我解决自己问题的方法。
首先,沟渠FormWizard。
我有一张表格。
两种观看次数:buy_apples
和buy_apples_confirm
第一个视图只处理GET。它打印出未绑定的表单,并带有转到第二个视图的URL的操作。
第二个视图检查是否存在名为“confirm”的POST参数。如果它不存在(因为它不是第一次加载视图时):
当用户点击购买苹果时,表单将被提交回来,并再次调用buy_apples_confirm
视图。这次,出现了一个名为“confirm”的POST参数,因此我们实际上处理了购买交易并且用户得到了他的苹果。
我欢迎对这种方法的任何批评或处理这种情况的更好方法。我是Django的新手,发现有很多不同的方法可以解决问题。我想从最好的方面学习。
答案 3 :(得分:0)
谢谢krys回答你自己的问题。帮助了我,但我仍有一些评论。
FormPreview不是要走的路,因为据我所知,它不支持动态表单。它依赖于固定的表单类来从那里生成from。但我们在这里用函数动态生成。也许FormPreview将支持这一天(或已经确实,我不知道如何)。
Krys解决方案似乎与FormPreview一样。只剩下哈希值,因此用户可以更改隐藏字段中的数据,还是再次检查?如果你再次检查它,那将不会跟随干,因为你复制了支票(好吧,可能是一个可重复使用的方法,所以只有很小的重复)。
我想知道,你如何调整小部件?您是否使用新窗口小部件复制表单,或者有没有办法动态更改它?
答案 4 :(得分:0)
如何更改调用方法以获取额外参数?