【问题标题】:Dynamically added Django FormSet data not being posted动态添加的 Django FormSet 数据未发布
【发布时间】:2016-07-17 13:55:52
【问题描述】:

我正在使用 JavaScript/jQuery 通过将表单动态添加到 Django FormSet 来修改 FormSet。例如,我从一个询问用户教育的表格开始。然后,用户可以按添加按钮添加相同的表格以输入有关中学教育(例如研究生院)的信息。表单被添加到浏览器中,我可以输入数据,但是当我发布数据时,它只在 FormSet 中显示一个表单,其中包含浏览器中第二个表单的信息。

发布数据

edu-0-degree    u'Doctorate'
first_name  u'User' 
last_name   u'One'
Submit  u'Submit'
edu-0-date_started  u'01/01/12'
edu-MIN_NUM_FORMS   u'0'
edu-0-school    u'School Two'
edu-INITIAL_FORMS   u'0'
edu-MAX_NUM_FORMS   u'1000'
edu-0-date_finished u'01/01/16'
edu-0-id    u''
edu-TOTAL_FORMS u'2'
csrfmiddlewaretoken u'qgD2supjYURWoKArWOmkiVRoBPF6Shw0'

然后我收到一条错误消息:

ValidationError: [u'ManagementForm data is missing or has been tampered with'].

以下是相关代码:

views.py

def build_profile(request):
    EducationFormset = modelformset_factory(EducationModel, AddEducationForm, extra=1)

    if request.method == "POST":

        education_formset = EducationFormset(request.POST, prefix='edu')
        for form in education_formset:
            if form.is_valid() and form.has_changed():
                education = EducationModel(
                    school = form.cleaned_data['school'],
                    date_started = form.cleaned_data['date_started'],
                    date_finished = form.cleaned_data['date_finished'],
                    degree = form.cleaned_data['degree'],
                    user = current_user
                )
                education.save()

        return HttpResponseRedirect(reverse('private', args=[current_user.username]))

    context = { 
        'edu_formset' : forms['education'],
    }

    return render(request, "build_profile.html", context)

(在这里,我尝试了使用和不使用 form.has_changed() ,结果相同。)

模板 build_profile.html

<h2>Education</h2>
{{ edu_formset.management_form }}
{% for form in edu_formset.forms %}
    <div id="{{ form.prefix }}-row" class="dynamic-form">
        {{ form|crispy }}
        <div {% if forloop.first %} class="hidden" {% endif %}>
            <button type="button" class="btn btn-default btn-sm delete-row">
                <span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
            </button>
        </div>
    </div>
{% endfor %}
<div class="btn-group btn-group-xs" role="group" aria-label="...">
    <button type="button" class="btn btn-default add-row">
        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
    </button>
</div>

build_profile.js(动态添加表单到 FormSet 的代码)

function updateElementIndex(el, prefix, ndx) {

    var id_regex = new RegExp('(' + prefix + '-\\d+)');
    var replacement = prefix + '-' + ndx;
    if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
    if (el.id) el.id = el.id.replace(id_regex, replacement);
    if (el.name) el.name = el.name.replace(id_regex, replacement);

}

function addForm(btn, prefix) {

    var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
    var row = $('.dynamic-form:first').clone(true).get(0);
    $(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
    $(row).children().not(':last').children().each(function() {
        updateElementIndex(this, prefix, formCount);
        $(this).val('');
    });
    $(row).find('.delete-row').click(function() {
        deleteForm(this, prefix);
    });
    $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
    return false;

}

function deleteForm(btn, prefix) {

    $(btn).parents('.dynamic-form').remove();
    var forms = $('.dynamic-form');
    $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
    for (var i=0, formCount=forms.length; i<formCount; i++) {
    $(forms.get(i)).children().not(':last').children().each(function() {
        updateElementIndex(this, prefix, i);
    });
}
return false;

}

$(document).ready( function () {

    $('.add-row').click( function () {
        return addForm(this, 'edu')
    });

    $('.delete-row').click( function () {
        return deleteForm(this, 'edu')
    });

});

我做错了什么?

【问题讨论】:

  • 我有几个问题。 1. 在您的表单的 html 中,您的 0-index 表单集中的字段有值。那些来自哪里? 2.你们中的management_form字段是post数据吗?你能告诉我们你的帖子数据是什么样的吗? 3. 您是否在尝试发布时遇到错误,还是仅在您添加表单时收到错误?
  • @RobVezina :我已经编辑了我的问题以包含我的帖子数据,而不是我之前包含的打印声明。浏览器中有两张表格都已填写,但似乎只有一张出现在帖子数据中。无论我是否添加了表单,我每次尝试发布时都会收到错误消息。

标签: javascript jquery python django-forms django-1.9


【解决方案1】:

您收到 ValidationError 是因为 edu_TOTAL-FORMS = 2 并且表单集中只有 1 个表单在您的帖子参数中。在浏览器中查看源代码并确保表单名称的前缀正确。看起来这两个表单都有 edu-0 前缀,并且当您提交时,只会发布表单上的最后一个。

【讨论】:

  • 感谢您的回答。分配的前缀存在问题。我想我现在已经改变了,当添加第二个表单时,前缀现在是“edu-1”而不是“edu-0”。但是,当我发布时,唯一带有“edu-1”前缀的是edu-1-id 变量。此外,以“edu-0”为前缀的帖子数据来自浏览器中的第二种形式,而不是第一种形式。我的edu-TOTAL-FORMS 是 2(我很确定应该是,因为我正在尝试提交两个表单)。我仍然收到相同的错误消息。 . .
  • 我将从页面中删除 javascript 开始。在您的表单集中使用多个表单。只有当你确定它在没有 javascript 的情况下工作时,你才应该重新添加 javascript 功能并开始调试它的那一部分。
  • 是的,你可能是对的。我会试一试,看看发生了什么。
猜你喜欢
  • 2020-07-22
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 2018-06-08
  • 2018-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多