使用相同的nam清除Django表单字段

2024-10-03 13:23:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个django模板,其中动态呈现多个字段(使用ajax) 下面是一个Django表单(在模板中呈现),其字段具有相同的名称。我想在将表单数据存储到数据库之前使用cleaned_data方法清除views.py中的表单数据。在

索引.html

<div class="form-container">
    <!-- ASSUMING I HAVE ALREADY ADDED FIELDS DYNAMICALLY -->
    <form id = "orderForm" action="newPickupOrder/" method="post" name="processForm">
        <input type='text' name='this_field'>
        <input type='text' name='this_field'>
        <button type="submit">Submit</button>
    </form>
</div>   

<form id="addItemForm">
    {% csrf_token %}
    <!-- BUTTON TO ADD MORE FIELDS DYNAMICALLY -->
    <button id = "addItemButton">Add item</button>
</form>

<script>
    var addItemButton = document.querySelector('#addItemButton');

    addItemButton.onclick = function(){            

        $.ajax({
            type: 'POST',
            url: 'addItem/',
            data: addItemForm.serialize(),
            success: function (response) {
                 $("#orderForm").append(response);                     
                 console.log('Success');
            },
            error: function (response) {                    
                console.log('Error = '+response);
            }
        });
    };
</script>

表单.py

^{pr2}$

网址.py

urlpatterns = [
    url(r'^newPickupOrder/$', views.pickup_order_view, name='new_pickup_order'),
]

视图.py

def add_item(request):
    if request.method == 'POST':
        itemForm = ItemForm()
        return HttpResponse(itemForm.as_p())

def pickup_order_view(request):
    if request.method == 'POST':
        form = ItemForm(request.POST)
        same_name_fields = request.POST.getlist('this_field')  
        # WANT TO CLEAN DATA IN same_name_fields

        if form.is_valid():
            print(form.cleaned_data)
            # ONLY PRINTS THE LAST FIELD's DATA
            return HttpResponseRedirect('/viewPickupRequests')              

我面临的问题是,如果我使用form.cleaned_data['this_field'],则只提取最后一个字段的数据,也就是说,在本例中,值为anotherTestValue的字段将被获取和清除。如果我使用request.POST.getlist('this_field')获取数据,那么所有字段的数据都将以列表的形式获取并存储,但是,我不知道如何使用cleaned_data方法清理它。有没有方法将cleaned_data方法应用于字段数据列表?在


Tags: 数据方法namepyform表单fielddata
2条回答

很抱歉,我不能测试这个是否有效,所以这不是一个真正的答案-但是注释系统不适合更大的代码块,所以我在这里发布。在

Django表单缺少一个呈现多个同名文本输入的字段类型。正确的做法是编写一个新的表单字段类和一个新的小部件。由于您没有在模板中呈现表单(您只将其用于验证),所以我将省略小部件部分。在

class AcceptAnythingMultipleChoiceField(forms.MultipleChoiceField):
    def validate(self, value):
        if self.required and not value:
            raise ValidationError(
                self.error_messages['required'], 
                code='required'
            )

然后使用这个field类而不是forms.CharField()(您可能需要传递一个空的choices参数)。在

[更新]

So essentially what you're saying is that I need to create new form field class and then render it to the template each time the user wants to add a new field? What if user has to add 15 fields, I'll need to create 15 classes then! I think this method won't be suitable in scenarios where number of fields required to be generated is large. I feel there should be some elegant way to do this which i'm not aware of – The OP

不,这不是我要说的。您可能需要像MultipleHiddenInput这样的子类,并将AcceptAnythingMultipleChoiceField.widget设置为它。您必须基于MultipleHiddenInput的模板创建一个新模板,并将type="text"的输入type="hidden"替换为django/forms/widgets/multiple_hidden.html(原始模板是django/forms/widgets/multiple_hidden.html)。在

^{pr2}$

如果您使用以下命令,则在前端为实例化的表单呈现所需数量的<input name='this_field'>

{{ form.this_field }}

在模板中,但不会动态添加/删除它们。在

为了做到这一点,您必须在小部件中插入动态添加/删除输入所需的JavaScript,但我将把这作为练习留给您。查看文档中的Form Assets (the Media class),以找出如何做到这一点。在

我想你要的是表格集。https://docs.djangoproject.com/en/2.0/topics/forms/formsets/

from django.forms import formset_factory

ItemFormSet = formset_factory(ItemForm, extra=2)

除了这个对象是iterable之外,您可以像使用普通形式一样使用ItemFormSet。在

如果要动态添加项,还必须更改jquery。网上有很多这样的例子。简而言之,你所做的是

  1. 克隆窗体集中的一个窗体
  2. 清除复制表单中的所有值
  3. 更新输入的(前缀)id

Using Formsets doesn't solve the problem of fetching and validating fields with same name. The issue still remains

但它确实会产生您想要的最终结果(见下文)。我的问题是为什么你需要有相同名称的输入?如果有一些jquery的东西使用这些名字,我不认为有任何理由你不能使用像。。。或者为输入指定一个类。在

^{pr2}$

模板

<form id = "orderForm" action="newPickupOrder/" method="post" name="processForm">
    {% csrf_token %}
    {{ item_formset.management_form }}
    {{ for item_form in item_formset }}
        {{ item_form.as_p }}
    {{ endfor }}

    <input type='submit' value='submit'>
</form>

转到newpickupporder/,填写5个字段,点击submit,然后看着它打印您的列表。在

相关问题 更多 >