2010-11-27 69 views
7

我在模板中放置了一些客户端Javascript,允许用户动态添加字段到表单。我的问题是这些字段已在form.cleaned_data中清除,所以我无法以这种方式访问​​它们。动态添加的表单域在form.cleaned_data中被删除

所有的字段都可以在request.POST访问,所以我可以用这个来解决这个问题,但我想这样做是“正确的方式”,我认为解决方案在于使用django表单而不是读取请求直。

我试着覆盖form.clean(),但是好像数据在它到达那里时已经消失了。

其他详情:我命名这些字段fieldname_x,其中x是一个数字。在request.POST中,request.POST['fieldname']是所有值的列表,但form.cleaned_data仅包含每个列表的最后一个值。

回答

2

你知道这些字段事先将会是什么类型吗?他们只是简单的文本字段?我做了类似的事情,创建了动态表单。

# make sure these exist by examining request.POST 
custom_fields = ['fieldname_1', 'fieldname_2'] 

attrs = dict((field, forms.CharField(max_length=100, required=False)) 
      for field in custom_fields) 
DynamicForm = type("DynamicForm", (YourBaseForm,), attrs) 
submitted_form = DynamicForm(request.POST) 

您提交的表单现在应该包含您需要的所有字段及其值。你可能想删除required = False,但这取决于你。

这是做什么的,是执行你的基本形式的动态子类,将作为attrs传入的属性添加到类定义中。因此,当您使用发布数据创建实例时,应该正确映射它们。

编辑:

我仔细地读了一下这个问题。你需要做的是确保你的动态输入元素被正确命名,并且值到达django后映射到这些字段名。否则,request.POST将不会正确填写表单。

<input type='text' name='fieldname_1' value='value_for_field_1' /> 

0

我在我目前工作的项目这样做。你会想看看formsets。但要警告,这不是很漂亮。你必须修改这个存储到表单计数的隐藏字段,并且你必须正确地重命名输入。这涉及到很多无意义的字符串解析。如果他们使用的阵列,如PHP,就不会有问题,但他们一意孤行在使我的生活苦不堪言...... 漫步关

编辑: http://docs.djangoproject.com/en/dev/topics/forms/formsets/#empty-form他们提供这使得你的生活5%少痛苦...你可以做一个发现和前缀用适当的号码替换..但我认为我有一个问题,空表单不包含正确的默认值,如果你初始化形式与发布数据,所以我不得不创建一个没有发布数据的第二个实例到一个实际为空的empty_form,这只是迟缓。

+0

拉尔夫,我建议你已经走了关于它的很长的路要走。利用python和Django系统做事。在需要时动态创建模型和表单。看到我的答案。 – 2010-11-28 01:01:36

2

也可以在你的表单文件中完成这项工作,这里是Jacob Kaplan-Mosse为动态表单提供的一个很好的演示:http://jacobian.org/writing/dynamic-form-generation/适用于这个问题。

做什么是添加一个方法给你表单类添加额外的动态字段,然后从干净的信息产生,以便您可以在您的视图中获得它。

class MyForm(forms.Form): 
    text = forms.CharField(max_length=30) 

    def __init__(self, *args, **kwargs): 
     extra = kwargs.pop('extra') 
     super(MyForm, self).__init__(*args, **kwargs) 

     for i, question in enumerate(extra): 
      self.fields['fieldname_%s' % i] = forms.CharField(label=question) 

    def extra_fields(self): 
     for name, value in self.cleaned_data.items(): 
      if name.startswith('fieldname_'): 
       yield (self.fields[name].label, value) 

,并从该视图调用它:

def doSomething(request, extra_fields): 
    form = MyForm(request.POST or None, extra=extra_fields) 
    if form.is_valid(): 
     for (question, answer) in form.extra_answers(): 
      save_answer(request, question, answer) 
     return redirect("create_user_success") 

return render_to_response("template/form.html", {'form': form}) 

非常整洁,恭喜雅各卡普兰,莫斯