Как правильно сделать редирект из мультиформы на нужную страницу в шаблоне django при помощи javascript

Рейтинг: 0Ответов: 1Опубликовано: 13.05.2023

Имеется страница загрузки файла, после нажатия на кнопку Загрузить, пользователь перемещается на мультиформу, которая работает при помощи javascript.

Вот пример формы:

Некоторые стили

<style>
* {
  box-sizing: border-box;
}

h1 {
  text-align: center;
}

input {
  padding: 10px;
  width: 100%;
  font-size: 17px;
}

/* Mark input boxes that gets an error on validation: */
input.invalid {
  background-color: #ffdddd;
}

/* Hide all steps by default: */
.card-body {
  display: none;
}

</style>

Шаблон страницы с формой

<form method="post" id="regForm" action="">
    {% csrf_token %}
    <!-- Display spectrum -->
        <div class="card">
            <div class="card-header">
                <nav class="navbar navbar-expand-md" style="width: 100%;">
                  <div class="navbar-collapse collapse w-100 order-1 order-md-0 dual-collapse2">
                    <ul class="navbar-nav mr-auto" style="margin: 0px !important;">
                      <li class="previous"><button type="button" class="fakeRef" id="prevBtn" onclick="nextPrev(-1)"><fa-icon [icon]="faArrowLeft"></fa-icon> Назад</button></li>
                    </ul>
                  </div>
                  <div class="mx-auto order-0">
                    <ul class="navbar-nav mx-auto">
                      <li><strong style="font-size: 1.2em;">Spectrum Viewer</strong></li>
                    </ul>
                  </div>
                  <div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
                    <ul class="navbar-nav ml-auto">
                      <li class="next"><button type="button" class="fakeRef" id="nextBtn" onclick="nextPrev(1)">Далее <fa-icon [icon]="faArrowRight"></fa-icon></button></li>
                    </ul>
                  </div>
                </nav>
            </div>

            <div class="card-body">
                Содержимое с input
            </div>

            <div class="card-body">
                Содержимое с input
            </div>

            <div class="card-body">
                Содержимое с input
            </div>
            <div class="card-footer" style="overflow:auto;">
                <nav class="navbar navbar-expand-md" style="width: 100%;">
                <div class="navbar-collapse collapse w-100 order-1 order-md-0 dual-collapse2">
                  <ul class="navbar-nav mr-auto" style="margin: 0px !important;">
                    <li class="previous"><button type="button" class="fakeRef" id="prevBtn1" onclick="nextPrev(-1)"><fa-icon [icon]="faArrowLeft"></fa-icon> Назад</button></li>
                  </ul>
                </div>
                <div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
                  <ul class="navbar-nav ml-auto">
                    <li class="next"><button type="button" class="fakeRef" id="nextBtn1" onclick="nextPrev(1)">Далее <fa-icon [icon]="faArrowRight"></fa-icon></button></li>
                  </ul>
                </div>
              </nav>
            </div>
        </div>
</form>

    </div>
</div>

Скрипт, который переключает формы

<script>
var currentTab = 0; // Current tab is set to be the first tab (0)
showTab(currentTab); // Display the current tab

function showTab(n) {
  // This function will display the specified tab of the form...
  var x = document.getElementsByClassName("card-body");
  x[n].style.display = "block";
  //... and fix the Previous/Next buttons:
  if (n == 0) {
    document.getElementById("prevBtn").innerHTML = "Отмена";
    document.getElementById("prevBtn1").innerHTML = "Отмена";
  } else {
    document.getElementById("prevBtn").style.display = "inline";
    document.getElementById("prevBtn1").style.display = "inline";
    document.getElementById("prevBtn").innerHTML = "Назад";
    document.getElementById("prevBtn1").innerHTML = "Назад";
  }
  if (n == (x.length - 1)) {
    document.getElementById("nextBtn").innerHTML = "Сохранить";
    document.getElementById("nextBtn1").innerHTML = "Сохранить";
  } else {
    document.getElementById("nextBtn").innerHTML = "Далее";
    document.getElementById("nextBtn1").innerHTML = "Далее";
  }
}

function nextPrev(n) {
  // This function will figure out which tab to display
  var x = document.getElementsByClassName("card-body");
  // Exit the function if any field in the current tab is invalid:
  if (n == 1 && !validateForm()) return false;
  // Hide the current tab:
  x[currentTab].style.display = "none";
  // Increase or decrease the current tab by 1:
  currentTab = currentTab + n;
  // if you have reached the end of the form...
  if (currentTab >= x.length) {
    // ... the form gets submitted:
    document.getElementById("regForm").submit();
    return false;
  }

  // Otherwise, display the correct tab:
  showTab(currentTab);
}

function validateForm() {
  // This function deals with validation of the form fields
  var x, y, i, valid = true;
  x = document.getElementsByClassName("card-body");
  y = x[currentTab].getElementsByTagName("input");
  // A loop that checks every input field in the current tab:
  for (i = 0; i < y.length; i++) {
    // If a field is empty...
    if (y[i].value == "") {
      // add an "invalid" class to the field:
      y[i].className += " invalid";
      // and set the current valid status to false
      valid = false;
    }
  }
  // If the valid status is true, mark the step as finished and valid:
  return valid; // return the valid status
}


function addField() {
        var form = $("#metadataForm");
        var index = Number(form.children().last().attr("index")) + 1;
        form.append(
            '<div class="input-group mb-3" id="metadataField' + index + '" index="' + index + '" }}>' +
                '<div class="col-sm-5 form-group"><input name="x' + index + '" type="text" class="form-control" placeholder="Имя поля" value=""></div>' +
                '<div class="col-sm-5 form-group"><input name="y' + index + '" type="text" class="form-control" placeholder="Значение" value=""></div>' +
                '<div class="col-sm-2 form-group"><button class="btn btn-outline-secondary" type="button" id="button-addon2" onclick="removeField(' + index + ');">Удалить</button></div>' +
            '</div>'
        );
    }

    function removeField(id) {
        $("#metadataField" + id).remove();
    }
</script>

Находясь на первой странице сверху и снизу отображаются кнопки Отмена и Далее, при нахождении на промежуточных страницах отображаются Назад и Далее, при нахождении на последней странице - Назад и Сохранить. При нажатии на Сохранить происходит submit формы с POST запросом во view. Там я получаю переданные из input-ов значения. При нажатии на первой странице на кнопку Отмена мне нужно, чтобы пользователь был перенаправлен обратно на страницу загрузки файла, откуда он пришел в форму после загрузки файла (return render(request, 'spectra/upload/upload_file.html')), но в текущей версии кода у меня пользователю отображается только верхняя и нижняя часть навигационной панели с кнопками Отмена и Далее. Дополнительный вопрос: как при сохранении данных с формы получить все данные из инпутов, но чтобы они были сложены в отдельные списки или словари, например. Сейчас у меня используется только одна форма (как в примере), если устанавливать формы на каждую вкладку, то соберутся данные только с той, по которой будет сделан submit.

Ответы

▲ 1

Сам разобрался методом тыка. Изменил код в javascript Поправил условия отображения страниц и условие при котором срабатывает submit на форму, которую я перехватываю в представлении и делаю редирект на нужную страницу.

<script type="text/javascript">
var currentTab = 0; // Current tab is set to be the first tab (0)
showTab(currentTab); // Display the current tab

function showTab(n) {
  // This function will display the specified tab of the form...
  var x = document.getElementsByClassName("card-body");
  x[n].style.display = "block";
  //... and fix the Previous/Next buttons:
  if (n == 0) {
    document.getElementById("prevBtn").innerHTML = "Отмена";
    document.getElementById("prevBtn1").innerHTML = "Отмена";
  } else {
    document.getElementById("prevBtn").innerHTML = "Назад";
    document.getElementById("prevBtn1").innerHTML = "Назад";
  }
  if (n == (x.length - 1)) {
    document.getElementById("nextBtn").innerHTML = "Сохранить";
    document.getElementById("nextBtn1").innerHTML = "Сохранить";
  } else {
    document.getElementById("nextBtn").innerHTML = "Далее";
    document.getElementById("nextBtn1").innerHTML = "Далее";
  }
}

function nextPrev(n) {
  // This function will figure out which tab to display
  var x = document.getElementsByClassName("card-body");
  // Exit the function if any field in the current tab is invalid:
  if (n == 1 && !validateForm()) return false;
  if (n == -1 && currentTab == 0) {
    // ... the form gets submitted:
    document.getElementById("cancelUploading").submit();
    return false;
  }
  // Hide the current tab:
  x[currentTab].style.display = "none";
  // Increase or decrease the current tab by 1:
  currentTab = currentTab + n;
  // if you have reached the end of the form...
  if (currentTab >= x.length) {
    // ... the form gets submitted:
    document.getElementById("regForm").submit();
    return false;
  }

  // Otherwise, display the correct tab:
  showTab(currentTab);
}

function validateForm() {
  // This function deals with validation of the form fields
  var x, y, i, valid = true;
  x = document.getElementsByClassName("card-body");
  y = x[currentTab].getElementsByTagName("input");
  // A loop that checks every input field in the current tab:
  for (i = 0; i < y.length; i++) {
    // If a field is empty...
    if (y[i].value == "") {
      // add an "invalid" class to the field:
      y[i].className += " invalid";
      // and set the current valid status to false
      valid = false;
    }
  }
  // If the valid status is true, mark the step as finished and valid:
  return valid; // return the valid status
}


function addField() {
        var div = $("#metadataFields");
        var index = Number(div.children().last().attr("index")) + 1;
        div.append(
            '<div class="input-group mb-3" id="metadataField' + index + '" index="' + index + '" }}>' +
                '<div class="col-sm-5 form-group"><input name="x' + index + '" type="text" class="form-control" placeholder="Имя поля" value=""></div>' +
                '<div class="col-sm-5 form-group"><input name="y' + index + '" type="text" class="form-control" placeholder="Значение" value=""></div>' +
                '<div class="col-sm-2 form-group"><button class="btn btn-outline-secondary" type="button" id="button-addon2" onclick="removeField(' + index + ');">Удалить</button></div>' +
            '</div>'
        );
    }

    function removeField(id) {
        $("#metadataField" + id).remove();
    }
</script>