为了账号安全,请及时绑定邮箱和手机立即绑定

动态将字段添加到表单

/ 猿问

动态将字段添加到表单

偶然的你 2019-10-06 15:51:35

我的表格中有3个字段。我有一个提交按钮和一个“添加其他字段”按钮。我知道我可以使用__init__表单类中的方法添加字段。


我是Python和Django的新手,并且陷入了一个初学者的问题:我的问题是:


当我单击“添加其他字段”按钮时,添加其他字段的过程是什么?


是否需要再次呈现表单?


我如何以及何时打电话__init__,甚至必须打电话?


如何将参数传递给__init__?



查看完整描述

3 回答

?
天涯尽头无女友

您的表单必须基于从POST传递给它的一些变量来构造(或盲目检查属性)。每次重新加载视图时(无论是否加载)都会构造表单本身,因此HTML需要包含有关构造正确数量的字段以进行验证的字段数量的信息。


我将以FormSet工作方式看一下这个问题:有一个隐藏字段,其中包含活动表单的数量,每个表单名称前都带有表单索引。


实际上,您可以将一个字段 FormSet


https://docs.djangoproject.com/en/dev/topics/forms/formsets/#formsets


如果您不想使用a FormSet,则可以随时自行创建此行为。


这是从头开始制作的-它应该给您一些想法。它还回答了有关将参数传递给的问题__init__-您只需将参数传递给对象构造函数:MyForm('arg1', 'arg2', kwarg1='keyword arg')


形式

class MyForm(forms.Form):

    original_field = forms.CharField()

    extra_field_count = forms.CharField(widget=forms.HiddenInput())


    def __init__(self, *args, **kwargs):

        extra_fields = kwargs.pop('extra', 0)


        super(MyForm, self).__init__(*args, **kwargs)

        self.fields['extra_field_count'].initial = extra_fields


        for index in range(int(extra_fields)):

            # generate extra fields in the number specified via extra_fields

            self.fields['extra_field_{index}'.format(index=index)] = \

                forms.CharField()

视图

def myview(request):

    if request.method == 'POST':

        form = MyForm(request.POST, extra=request.POST.get('extra_field_count'))

        if form.is_valid():

            print "valid!"

    else:

        form = MyForm()

    return render(request, "template", { 'form': form })

的HTML

<form>

    <div id="forms">

        {{ form.as_p }}

    </div>

    <button id="add-another">add another</button>

    <input type="submit" />

</form>

JS

<script>

form_count = Number($("[name=extra_field_count]").val());

// get extra form count so we know what index to use for the next item.


$("#add-another").click(function() {

    form_count ++;


    element = $('<input type="text"/>');

    element.attr('name', 'extra_field_' + form_count);

    $("#forms").append(element);

    // build element and append it to our forms container


    $("[name=extra_field_count]").val(form_count);

    // increment form count so our view knows to populate 

    // that many fields for validation

})

</script>


查看完整回答
反对 回复 2019-10-06
?
互换的青春

我曾经遇到过必须动态创建带有动态字段的表单的情况。我用这个技巧做到了:


from django import forms


...


dyn_form = type('DynForm',  # form name is irrelevant

                (forms.BaseForm,),

                {'base_fields': fields})

请参阅此链接以获取更多信息: 动态表单


但是除此之外,我还必须注入字段,即在创建表单类后将其动态添加到表单类中。


dyn_form.base_fields['field1'] = forms.IntegerField(widget=forms.HiddenInput(), initial=field1_val)

dyn_form.base_fields['field2'] = forms.CharField(widget=forms.HiddenInput(), initial=field2_val)

那行得通。


查看完整回答
反对 回复 2019-10-06
?
慕田峪7331174

该答案基于@ Yuji'Tomita'Tomita的改进和更改。


尽管@ Yuji'Tomita'Tomita的回答很好,并且很好地说明了构建“以django形式添加额外字段”功能的方向,但我发现代码的某些部分存在一些问题。


在这里,我根据@ Yuji'Tomita'Tomita的初步建议提供工作代码:


视图 (在view.py文件中)


视图中并没有真正改变:


def myview(request):


  if request.method == 'POST':


    form = MyForm(request.POST, extra=request.POST.get('total_input_fields'))


      if form.is_valid():

        print "valid!"

      else:

        form = MyForm()

return render(request, "template", { 'form': form })

表格(在form.py文件中)


class MyForm(forms.Form):


    empty_layer_name = forms.CharField(max_length=255, required=True, label="Name of new Layer")


    total_input_fields = forms.CharField(widget=forms.HiddenInput())



    def __init__(self, *args, **kwargs):


      extra_fields = kwargs.pop('extra', 0)


      # check if extra_fields exist. If they don't exist assign 0 to them

      if not extra_fields:

         extra_fields = 0


      super(MyForm, self).__init__(*args, **kwargs)

      self.fields['total_input_fields'].initial = extra_fields


      for index in range(int(extra_fields)):

        # generate extra fields in the number specified via extra_fields

        self.fields['extra_field_{index}'.format(index=index)] = forms.CharField()

模板HTML


<form id="empty-layer-uploader" method="post" enctype="multipart/form-data" action="{% url "layer_create" %}">

        <div id="form_empty_layer">

          <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">

            {{ form.errors }}

            {{ form.non_field_errors }}

            {% if errormsgs %}

              {% for value in errormsgs %}

                </p>  {{ value }} </p>

              {% endfor %}

            {% endif %}

            {% for error in form_empty_layer.non_field_errors %}

              {{ error }} </br>

            {% endfor %}

            </br>

            {% for field in form_empty_layer.visible_fields %}

              {{ field }} </br>

            {% endfor %}

        </div>

        </br>

        <button type="button" id="add-another">add another</button> </br> </br>

        <button type="submit" id="empty-layer-button" name="emptylayerbtn">Upload</button>

        </br></br>

        // used in order to save the number of added fields (this number will pass to forms.py through the view)

        <input type="text" name="total_input_fields"/>

</form>

模板jQuery


// check how many times elements with this name attribute exist: extra_field_*

form_count = $('input[name*="extra_field_*"]').length;


// when the button 'add another' is clicked then create a new input element

$(document.body).on("click", "#add-another",function(e) {

  new_attribute = $('<input type="text"/>');

  // add a name attribute with a corresponding number (form_count)

  new_attribute.attr('name', 'extra_field_' + form_count);

  // append the new element in your html

  $("#form_empty_layer").append(new_attribute);

  // increment the form_count variable

  form_count ++;

  // save the form_count to another input element (you can set this to invisible. This is what you will pass to the form in order to create the django form fields

  $("[name=total_input_fields]").val(form_count);


})


查看完整回答
反对 回复 2019-10-06

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信