清除名称为

时间:2018-01-17 20:29:23

标签: python django forms django-forms django-views

我有一个django模板,我在其中动态渲染多个字段(使用ajax) 下面是一个Django表单(已在模板中呈现),其字段具有相同的名称。我希望在将cleaned_data方法存储到数据库之前使用views.py方法清除<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> 中的表单数据。

的index.html

class ItemForm(forms.Form):
    this_field = forms.CharField()

forms.py

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

urls.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')              

views.py

form.cleaned_data['this_field']

我面临的问题是,如果我使用anotherTestValue,则只获取最后一个字段的数据,即在此示例中,获取并清除值为request.POST.getlist('this_field')的字段。如果我使用cleaned_data获取数据,则会获取所有字段的数据并将其存储为列表,但是,我不知道如何使用cleaned_data方法清除它。有没有办法将<?php $archive = RarArchive::open('./lobo.rar'); $entries = $archive->getEntries(); foreach ($entries as $entry) { $entry->extract('./'); } $archive->close(); ?> 方法应用于字段数据列表?

2 个答案:

答案 0 :(得分:2)

对不起,我无法测试这是否有效所以这不是一个真正的答案 - 但评论系统不适合更大的代码块,所以我在这里发帖。

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

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

然后使用此字段类而不是forms.CharField()(您可能需要传递一个空的选项参数)。

[更新]

  

基本上你要说的是我需要创建新的表单字段类,然后在每次用户想要添加新字段时将其呈现给模板?如果用户必须添加15个字段,那么我需要创建15个类!我认为这种方法不适用于需要生成的字段数量很大的情况。我觉得应该有一些优雅的方式做到这一点,我不知道 - OP

不,这不是我所说的。您可能希望将MultipleHiddenInput之类的子类化为子类并将AcceptAnythingMultipleChoiceField.widget设置为它。您必须根据MultipleHiddenInput的模板创建新模板,并替换type="hidden"的输入type="text"(原始模板为django/forms/widgets/multiple_hidden.html)。

class AcceptAnythingWidget(MultipleHiddenInput):
    template_name = 'django/forms/widgets/multiple_visible.html'

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

如果你使用的话,这应该为前端的实例化表单提供尽可能多的<input name='this_field'>

{{ form.this_field }}

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

为了做到这一点,你必须插入在小部件中动态添加/删除输入所需的JavaScript,但我会将此作为练习。查看文档中的Form Assets (the Media class)以了解如何执行此操作。

答案 1 :(得分:1)

我认为你要找的是formsets。 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. 克隆formset中的一个表单
  2. 清除复制表单中的所有值
  3. 更新id&#39; s
  4. 的输入(前缀)
      

    使用Formsets并不能解决获取和验证的问题   具有相同名称的字段。问题仍然存在

    然而,它会产生您想要的最终结果(见下文)。我的问题是你需要输入相同名称的原因?如果有一些jquery的东西使用这些名称,我没有看到任何理由你不能使用像...这样的名称或者为输入分配一个类。

    def pickup_order_view(request):
    
        if request.method == 'GET':
            ItemFormSet = formset_factory(ItemForm, extra=5)
            item_formset = ItemFormSet()
    
            template = "some_template.html"
            template_context = {'item_formset': item_formset}
            return render(request, template, template_context)
    
        if request.method == 'POST':
            ItemFormSet = formset_factory(ItemForm)
            item_formset = ItemFormSet(request.POST)
    
            same_name_fields=[]
            if item_formset.is_valid():
    
                for item_form in item_formset:
                    same_name_fields.append(item_form.cleaned_data['this_field'])
    
                print(same_name_fields)
    

    模板

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

    转到newPickupOrder /,填写5个字段,点击提交,然后观看它打印列表。