Динамически добавленные данные Django FormSet не публикуются

Я изменяю FormSet с помощью JavaScript/jQuery, динамически добавляя форму в Django 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')
    });

});

Что я делаю не так?


person eswens13    schedule 29.03.2016    source источник
comment
У меня есть пара вопросов. 1. В вашем html для вашей формы есть значения для полей в вашем наборе форм с 0-индексом. Откуда приходят? 2. Есть ли поля management_form в ваших постах? Не могли бы вы показать нам, как выглядят данные вашего поста? 3. Вы получаете сообщение об ошибке каждый раз, когда пытаетесь опубликовать сообщение, или только если вы добавили форму?   -  person Rob Vezina    schedule 30.03.2016
comment
@RobVezina: я отредактировал свой вопрос, включив в него данные моего сообщения, а не заявление о печати, которое я включил ранее. В браузере было две формы, которые были заполнены, но, похоже, только одна из них отображается в данных сообщения. Я получаю сообщение об ошибке каждый раз, когда пытаюсь отправить сообщение, независимо от того, добавил ли я форму.   -  person eswens13    schedule 31.03.2016


Ответы (1)


Вы получаете ValidationError, потому что edu_TOTAL-FORMS = 2 и только 1 форма из набора форм находится в ваших аргументах сообщения. Просмотрите исходный код в браузере и убедитесь, что имена ваших форм имеют правильный префикс. Похоже, что обе формы имеют префикс edu-0, и когда вы отправляете, публикуется только последняя форма.

person Rob Vezina    schedule 01.04.2016
comment
Спасибо за ваш ответ. Возникла проблема с назначением префиксов. Я думаю, что изменил это сейчас, так что при добавлении второй формы префикс теперь будет «edu-1» вместо «edu-0». Однако, когда я публикую, единственное, что появляется с префиксом «edu-1», — это переменная edu-1-id. Кроме того, данные сообщения с префиксом «edu-0» поступают из второй формы в браузере, а не из первой. Мой edu-TOTAL-FORMS равен 2 (я уверен, что так и должно быть, поскольку я пытаюсь отправить две формы). Я все еще получаю то же сообщение об ошибке. . . - person eswens13; 04.04.2016
comment
Я бы начал с удаления javascript со страницы. Получите это, работая с несколькими формами в вашем наборе форм. Только когда вы уверены, что он работает без javascript, вы должны добавить функциональность javascript обратно и начать отладку этой его части. - person Rob Vezina; 05.04.2016
comment
Да, наверное, ты прав. Я попробую и посмотрю, что происходит. - person eswens13; 05.04.2016