创建具有动态字段数量的Django表单类

61 投票
5 回答
76026 浏览
提问于 2025-04-16 14:40

我正在做一个类似在线商店的项目。我想制作一个表单,让顾客可以购买商品,并选择她想买多少件。不过,每件商品在购买时都需要选择颜色。所以,表单中的字段数量是不固定的:如果顾客买了3件商品,她就应该看到3个选择颜色的下拉框;如果她买了7件商品,那就应该有7个这样的下拉框。

我打算用JavaScript来控制这些HTML表单字段的显示和隐藏。但是,我该如何在我的Django表单类中处理这个问题呢?我发现表单字段是类的属性,所以我不太清楚如何处理某些表单实例需要3个颜色字段,而有些需要7个的问题。

有没有什么建议呢?

5 个回答

22

你可以这样做:

def __init__(self, n,  *args, **kwargs):
  super(your_form, self).__init__(*args, **kwargs)
  for i in range(0, n):
    self.fields["field_name %d" % i] = forms.CharField()

然后当你创建表单实例时,你只需要这样做:

forms = your_form(n)

这只是一个基本的想法,你可以根据自己的需要修改代码。:D

39

这里还有一个选择:你考虑过使用表单集吗?因为你的字段都是一样的,表单集正好就是用来处理这种情况的。

Django的管理后台使用FormSet加上一点JavaScript来添加任意长度的内嵌表单。

class ColorForm(forms.Form):
    color = forms.ChoiceField(choices=(('blue', 'Blue'), ('red', 'Red')))

ColorFormSet = formset_factory(ColorForm, extra=0) 
# we'll dynamically create the elements, no need for any forms

def myview(request):
    if request.method == "POST":
        formset = ColorFormSet(request.POST)
        for form in formset.forms:
            print "You've picked {0}".format(form.cleaned_data['color'])
    else:
        formset = ColorFormSet()
    return render(request, 'template', {'formset': formset}))

JavaScript

    <script>
        $(function() {
            // this is on click event just to demo.
            // You would probably run this at page load or quantity change.
            $("#generate_forms").click(function() {
                // update total form count
                quantity = $("[name=quantity]").val();
                $("[name=form-TOTAL_FORMS]").val(quantity);  

                // copy the template and replace prefixes with the correct index
                for (i=0;i<quantity;i++) {
                    // Note: Must use global replace here
                    html = $("#form_template").clone().html().replace(/__prefix_/g', i);
                    $("#forms").append(html);
                };
            })
        })
    </script>

模板

    <form method="post">
        {{ formset.management_form }}
        <div style="display:none;" id="form_template">
            {{ formset.empty_form.as_p }}
        </div><!-- stores empty form for javascript -->
        <div id="forms"></div><!-- where the generated forms go -->
    </form>
    <input type="text" name="quantity" value="6" />
    <input type="submit" id="generate_forms" value="Generate Forms" />
76

Jacob Kaplan-Moss 写了一篇关于动态表单字段的详细文章:http://jacobian.org/writing/dynamic-form-generation/

简单来说,就是在创建表单的时候,你可以往表单的 self.fields 字典里添加更多的项目。

撰写回答