У меня есть 2 вложенных набора форм, в которые я добавляю новые формы с помощью кнопки +.У меня есть BookForm, в которой пользователь может добавить несколько книг, а внутри BookForm есть форма DemoForm, пользователь также может добавить несколько форм DemoForm внутри формы книги.BookForm работает нормально, но для DemoForm идентификаторы не генерируются идеально, скорее это копия идентификатора предыдущей формы.
Я связал изображение ошибки.На рисунке вы можете увидеть, что для первой демонстрационной формы внутри 3-го идентификатора книжной формы такой же, как у предыдущих форм, то есть id_d-0-name3.Ошибка: Ссылка на изображение
Код: Forms.py:
class DemoForm(forms.Form):
name3 = forms.CharField(
label='publisher Name', required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Enter Publisher Name here',
'data-cnttype':'publisher'
}
)
)
class BookForm(forms.Form):
name = forms.CharField(
label='Book Name', required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Enter Book Name here',
'data-cnttype':'book'
}
)
)
class AuthorForm(forms.Form):
name2 = forms.CharField(
label='Author Name', required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Enter Author Name here'
}
)
)
BookFormset = formset_factory(BookForm, extra=1)
DemoFormset = formset_factory(DemoForm,extra=1)
Нам нужно исправить функцию Javascript, чтобы она могла создавать формы с увеличенным идентификационным номером дляDemoformset.HTML:
<html>
<head>
</head>
<body>
<form class="form-horizontal" method="POST"
action="http://127.0.0.1:8000/home/a/">
{% csrf_token %}
{{authorform}}
{{ formset.management_form }}
{{demo_formset.management_form}}
{% for form in formset %}
<div class="row form-row spacer">
<div class="col-2">
<label>{{form.name.label}}</label>
</div>
<div class="col-4">
<div class="input-group">
{{form.name}}
<div class="input-group-append">
<button class="btn btn-success add-form-row">+</button>
</div>
</div>
</div>
{% for form1 in demo_formset %}
<div class="row form-row1 spacer">
<div class="col-2">
<label>{{form1.name3.label}}</label>
</div>
<div class="col-4">
<div class="input-group">
{{form1.name3}}
{% endfor %}
</div>
<div class="input-group-append">
<button class="btn btn-success add-form-row1">+</button>
</div>
</div>
{% endfor %}
<div class="row spacer">
<div class="col-4 offset-2">
<button type="submit" class="btn btn-block btn-
primary">Create</button>
</div>
</div>
</div>
</div>
</form>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script type="text/javascript">
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 cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
if($(this).attr('name')){
var name = $(this).attr('name').replace('-' + (total-1) + '-',
'-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id':
id}).val('').removeAttr('checked');
}
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>');
return false;
}
function cloneMore1(selector, prefix) {
var newElement = $(selector).clone(true);
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
if($(this).attr('name')){
var name = $(this).attr('name').replace('-' + (total-1) + '-', '-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
}
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row1:not(:last)');
conditionRow.find('.btn.add-form-row1')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row1').addClass('remove-form-row1')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>');
return false;
}
function deleteForm(prefix, btn) {
var total = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (total > 1){
btn.closest('.form-row').remove();
var forms = $('.form-row');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).find(':input').each(function() {
updateElementIndex(this, prefix, i);
});
}
}
return false;
}
$(document).on('click', '.add-form-row', function(e){
e.preventDefault();
cloneMore('.form-row:last', 'f');
return false;
});
$(document).on('click', '.add-form-row1', function(e){
e.preventDefault();
cloneMore1('.form-row1:last', 'd');
return false;
});
$(document).on('click', '.remove-form-row', function(e){
e.preventDefault();
deleteForm('form', $(this));
return false;
});
</script>
</body>
</html>
Я использую Mongoengine, так что это будет немного по-другому.Model.py:
class Demo(EmbeddedDocument):
name3 = StringField(required=False)
class Book(EmbeddedDocument):
name = StringField(required=False)
name3 = ListField(EmbeddedDocumentField(Demo))
class Author(Document):
name2 = StringField(required=False)
names = ListField(EmbeddedDocumentField(Book))
Views.py:
def create_book_normal(request):
template_name = 'medli/home.html'
if request.method == 'GET':
authorform = AuthorForm(request.GET)
formset = BookFormset(request.GET or None, prefix='f')
demo_formset = DemoFormset(request.GET or None,prefix='d')
if request.method == 'POST':
authorform = AuthorForm(request.POST)
formset = BookFormset(request.POST or None, prefix='f')
demo_formset = DemoFormset(request.POST or None,prefix='d')
name_list = []
demo_list = []
i = -1
if formset.is_valid() and authorform.is_valid() and demo_formset.is_valid():
name2 = authorform.cleaned_data.get('name2')
c = Author()
for form in formset:
name = form.cleaned_data.get('name')
name_list.append(Book(name=name))
print("aaa", name)
#print(form)
c.name2 = name2
c.names = name_list
for demo_form in demo_formset:
name3 = demo_form.cleaned_data.get('name3')
demo_list.append(Demo(name3=name3))
print("bbb", name3)
#print(demo_form)
"""while(1):
print("came is while loop")
c.names[i].name3 = demo_list
print("I is:",i," object is:",c.names[i].name3)
i+=1
c.save()
break"""
i += 1
if i == 0:
c.names[0].name3 = demo_list
print(demo_list[0:1])
#c.save()
if i == 1:
c.names[1].name3 = demo_list
print(demo_list[1:2])
#c.save()
c.save()
#return redirect('medli/home.html')
return render(request, template_name, {
'authorform': authorform,'formset': formset, 'demo_formset' : demo_formset
})