Вложенная динамическая форма в Django с использованием Javascript - PullRequest
0 голосов
/ 07 марта 2019

У меня есть 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
})
...