动态添加的表单字段将在form.cleaned_data中删除

时间:2021-12-25 16:26:47

I put some client-side Javascript in my template that allows a user to dynamically add fields to a form. My problem is that these fields are cleaned in form.cleaned_data, so I can't access them that way.

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

All the fields are accessible in request.POST, so I could just solve this problem with that, but I want to do this the "right way" and I think that the solution lies somewhere in using django forms rather than reading the request directly.

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

I tried overriding form.clean(), but it seems like the data is already gone by the time it gets there.

我试过覆盖form.clean(),但似乎数据已经消失了。

Other details: I am naming these fields fieldname_x, where x is a number. In request.POST, request.POST['fieldname'] is a list of a all the values, but form.cleaned_data contains only the last value of each list.

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

3 个解决方案

#1


2  

Do you know what type these fields are going to be beforehand? Are they just going to be simple text fields? I've done something similar to this, creating dynamic forms.

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

# 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)

Your submitted form should now contain all the fields you require, along with their values. You might want to remove required=False, but that's up to you.

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

What this does, is perform a dynamic subclass of your base form, adding the attributes passed in as attrs to the class definition. So when you create an instance with post data, they should be mapped correctly.

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

Edit:

编辑:

I read the question a little more closely. What you'll want to do is ensure that your dynamic input elements are named correctly, and the values map to those fieldnames once it reaches django. Otherwise, request.POST will not fill the form in correctly.

我更仔细地阅读了这个问题。您要做的是确保正确命名动态输入元素,并且一旦到达django,值将映射到这些字段名。否则,request.POST将无法正确填写表单。

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

etc

等等

#2


2  

It is also possible to do this work in your form file, here is an excellent demonstration by Jacob Kaplan-Mosse for dynamic forms : http://jacobian.org/writing/dynamic-form-generation/ that applies quite well for this problem.

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

What is done is adding a methods to you form class that add the extra dynamic fields and then yields the information from the clean so that you can get it in your view.

所做的是为表单添加一个方法,添加额外的动态字段,然后从clean中生成信息,以便在视图中获取它。

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)

And to call it from the view :

并从视图中调用它:

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})

Very neat, congrats to Jacob Kaplan-Moss

非常整洁,恭喜Jacob Kaplan-Moss

#3


0  

I'm doing this in the project I'm currently working on. You'll want to have a look at formsets. But be warned, it isn't pretty. You have to modify this stupid hidden field that stores to the form count, and you have to rename the inputs correctly.. which involves a lot of pointless string parsing. If they had used arrays, like PHP, there wouldn't be an issue, but they're hell bent on making my life miserable... rambles off

我正在我正在进行的项目中这样做。你想看一下formset。但要注意,它并不漂亮。你必须修改存储到表单计数的这个愚蠢的隐藏字段,你必须正确地重命名输入..这涉及很多无意义的字符串解析。如果他们使用像PHP一样的数组,就不会有问题,但是他们一心想让我的生活变得悲惨......

Edit: http://docs.djangoproject.com/en/dev/topics/forms/formsets/#empty-form they provide this which makes your life 5% less painful... you can just do a find and replace on prefix with the appropriate number.. but I think I had an issue where the empty form doesn't contain the proper default values if you initialize the form with post data, so I had to create a 2nd instance without post data to an actually empty empty_form, which is just retarded.

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

#1


2  

Do you know what type these fields are going to be beforehand? Are they just going to be simple text fields? I've done something similar to this, creating dynamic forms.

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

# 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)

Your submitted form should now contain all the fields you require, along with their values. You might want to remove required=False, but that's up to you.

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

What this does, is perform a dynamic subclass of your base form, adding the attributes passed in as attrs to the class definition. So when you create an instance with post data, they should be mapped correctly.

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

Edit:

编辑:

I read the question a little more closely. What you'll want to do is ensure that your dynamic input elements are named correctly, and the values map to those fieldnames once it reaches django. Otherwise, request.POST will not fill the form in correctly.

我更仔细地阅读了这个问题。您要做的是确保正确命名动态输入元素,并且一旦到达django,值将映射到这些字段名。否则,request.POST将无法正确填写表单。

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

etc

等等

#2


2  

It is also possible to do this work in your form file, here is an excellent demonstration by Jacob Kaplan-Mosse for dynamic forms : http://jacobian.org/writing/dynamic-form-generation/ that applies quite well for this problem.

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

What is done is adding a methods to you form class that add the extra dynamic fields and then yields the information from the clean so that you can get it in your view.

所做的是为表单添加一个方法,添加额外的动态字段,然后从clean中生成信息,以便在视图中获取它。

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)

And to call it from the view :

并从视图中调用它:

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})

Very neat, congrats to Jacob Kaplan-Moss

非常整洁,恭喜Jacob Kaplan-Moss

#3


0  

I'm doing this in the project I'm currently working on. You'll want to have a look at formsets. But be warned, it isn't pretty. You have to modify this stupid hidden field that stores to the form count, and you have to rename the inputs correctly.. which involves a lot of pointless string parsing. If they had used arrays, like PHP, there wouldn't be an issue, but they're hell bent on making my life miserable... rambles off

我正在我正在进行的项目中这样做。你想看一下formset。但要注意,它并不漂亮。你必须修改存储到表单计数的这个愚蠢的隐藏字段,你必须正确地重命名输入..这涉及很多无意义的字符串解析。如果他们使用像PHP一样的数组,就不会有问题,但是他们一心想让我的生活变得悲惨......

Edit: http://docs.djangoproject.com/en/dev/topics/forms/formsets/#empty-form they provide this which makes your life 5% less painful... you can just do a find and replace on prefix with the appropriate number.. but I think I had an issue where the empty form doesn't contain the proper default values if you initialize the form with post data, so I had to create a 2nd instance without post data to an actually empty empty_form, which is just retarded.

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