Вы когда-нибудь пытались найти подробное руководство по созданию динамических форм с использованием Django, AJAX и jQuery? Вы могли заметить, их не так много. Вот где мы вступаем. В этом уроке мы глубоко погружаемся в мир создания динамических форм, которые адаптируются к пользовательскому вводу. К концу этого руководства у вас появится уникальный набор навыков, пользующихся большим спросом. Давайте начнем и овладеем искусством разработки динамических форм в области, где подробные руководства трудно найти.

Настройка проекта:
Прежде чем мы начнем, убедитесь, что Django настроен в вашем мире программирования. Если его еще нет, просто установите его с помощью вашего любимого инструмента. Как только Django заработает, создайте новый проект Django и назовите свое приложение «dynamic_form». Это будет наша площадка для создания динамических форм.

Создание URL-адресов:

from django.urls import path
from .views import index, submit

urlpatterns = [
    path('', index),
    path('submit/', submit)
]

Этот код определяет маршруты для нашей формы. Пустой маршрут («») ведет к основной форме, а «submit/» — это место, где обрабатываются отправки форм.

Создание моделей и форм (models.py и forms.py):

# models.py
from django.db import models

class Question(models.Model):
    question = models.CharField(max_length=200)

    def __str__(self):
        return self.question

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    answer = models.CharField(max_length=200)
    is_correct = models.BooleanField(default=False)

    def __str__(self):
        return self.answer
# forms.py
from django.forms import ModelForm
from .models import Answer

class AnswerForm(ModelForm):
    class Meta:
        model = Answer
        exclude = ['question']

В мире моделей мы определяем структуру наших данных, используя модели вопросов и ответов. Каждый вопрос имеет строковое поле, и каждый ответ связан с вопросом, а также содержит текстовый ответ и логический флаг, указывающий правильность.

Чтобы элегантно отразить эту структуру модели в формах, мы вводим класс AnswerForm как подкласс ModelForm Django. Указав модель как Ответ и исключив поле вопроса, мы создаем форму, которая идеально соответствует сути нашей модели.

Создание представлений:

Откройте файл views.py и посмотрите на это:

from django.shortcuts import render
from .forms import AnswerForm
from .models import Question, Answer

def index(request):
    form = AnswerForm()
    return render(request, 'core/index.html', {'form': form})

В этой части кода мы определяем функцию под названием index. Эта функция отвечает за отображение исходной формы, которую видят пользователи при посещении определенной веб-страницы. Мы используем класс AnswerForm, который предположительно определяет структуру нашей формы с полями типа «ответы[]» и «правильный_ответ». Эта форма предоставляется шаблону с именем index.html вместе с самим экземпляром формы.

Перейдем к функции отправки:

def submit(request):
    if request.method == 'POST':
        data = request.POST
        answers = data.getlist('answers[]')
        correct_answer = data.get('correct_answer')
        question = data.get('question')

        if len(answers) > 0:
            new_question = Question(question=question)
            new_question.save()

        for answer in answers:
            if answer == correct_answer:
                new_answer = Answer(question=new_question, answer=answer, is_correct=True)
                new_answer.save()
            else:
                new_answer = Answer(question=new_question, answer=answer)
                new_answer.save()

    return render(request, 'core/index.html')

Функция отправки вступает в действие при отправке формы, обычно когда пользователь нажимает кнопку «Отправить». Вот как это работает:

Он начинается с проверки того, является ли метод запроса «POST». Это означает, что данные были отправлены на сервер как часть отправки формы.

Если это действительно POST-запрос, он извлекает данные из отправленной формы с помощью request.POST.

Код извлекает значения из формы для трех полей: «ответы[]», «правильный_ответ» и «вопрос». Предполагается, что эти поля являются частью отправленной формы.

Если предоставлены ответы (список ответов не пуст), создается новый вопрос со значением «вопрос». Этот вопрос затем сохраняется в базе данных.

Затем код перебирает каждый ответ в списке ответов. Для каждого ответа он проверяет, соответствует ли он «правильному_ответу». Если это так, создается новый экземпляр ответа с полем is_correct, установленным в значение True; в противном случае создается экземпляр ответа со значением «is_correct» как False. В обоих случаях ответ связывается с ранее созданным вопросом, а новый экземпляр ответа сохраняется в базе данных.

Наконец, после обработки отправки формы и операций с базой данных, функция снова отображает шаблон index.html, возможно, с обновленной информацией.

Проектирование формы (HTML и JavaScript):

Вот полный код для HTML и JavaScript.

<!-- HTML Code -->
<form id="answer-form" method="post" action="{% url 'submit' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <div id="answer-container">
        <div class="answer-row">
            <input type="text" name="answers[]" class="answer-input" required>
            <button type="button" class="remove-answer">Remove Answer</button>
        </div>
    </div>
    <button type="button" id="add-answer">Add Answer</button>
    <button type="submit">Submit</button>
</form>

<script>
    // JavaScript Code
    var wrapper = $('#showItem');
    $('#addItemBtn').click((e) => {
        e.preventDefault();
        $(wrapper).append(`
            <div class="row">
                <div class="form-group mx-sm-3 mb-2">
                    <p>Answer</p>
                    {{forms.answer}}
                </div>
                <div class="form-group mx-sm-3 mb-2">
                    <p>is_correct</p>
                    {{forms.is_correct}}
                </div>
                <div class="mt-2">
                    <a class="btn btn-danger mb-2 color-white removeBtn" data-id="1" id="removeItemBtn">Remove</a>
                </div>
            </div>
        `);
    });

    $(wrapper).on("click", ".removeBtn", function(e) {
        e.preventDefault();
        $(this).parent('div').parent('div').remove();
    });

    const submit = document.getElementById('submit');
    submit.addEventListener('click', (e) => {
        e.preventDefault();
        const data = $('#testform').serializeArray();
        const csrf = document.getElementsByName('csrfmiddlewaretoken');
        var question = "";
        var answers = [];
        var correct_answer = "";

        for (let i = 0; i < data.length; i++) {
            const element = data[i];
            if (i === 0) {
                csrf[0].value = element['value'];
            } else {
                if (element['value'] !== "") {
                    if (element['name'] === "Question") {
                        question = element['value'];
                    } else if (element['name'] === "is_correct") {
                        correct_answer = data[i - 1]['value'];
                    } else {
                        answers.push(element['value']);
                    }
                }
            }
        }

        var datas = {};
        if (answers.length > 0) {
            datas['csrfmiddlewaretoken'] = csrf[0].value;
            datas['question'] = question;
            datas['answers'] = answers;
            datas['correct_answer'] = correct_answer;
            $.ajax({
                type: 'POST',
                url: '/submit/',
                data: datas,
                dataType: 'json',
                success: function() {
                    console.log("success");
                }
            });
        }


    });
</script>

Давайте разобьем этот сценарий JavaScript на простые шаги:

Готовимся:

var обертка = $('#showItem');:

Думайте о «обертке» как о бдительном помощнике, наблюдающем за областью с идентификатором «showItem». Это похоже на игровую площадку для оживления новых полей формы.

Создание новых полей:

$('#addItemBtn').click((e) =› { … });:

Эта часть похожа на магическое заклинание, которое активируется, когда вы щелкаете что-то с идентификатором «addItemBtn». Это все равно, что сказать: «Эй, когда нажмешь на эту кнопку, сделай вот эту крутую штуку!»

e.preventDefault();:

Это все равно, что сказать: «Подожди, не делай обычных действий при нажатии». Это дает нам контроль над тем, что произойдет дальше.

$(обертка).append(…);:

В этой части действительно происходит волшебство. Представьте, что у вас есть волшебная палочка, и вы одним движением руки создаете новый ряд полей формы. То, что находится внутри обратных кавычек (…), похоже на ингредиенты для новых полей формы.

Удаление полей:

$(wrapper).on(“click”, “.removeBtn”, function(e) { … });:

Здесь мы отслеживаем клики внутри области «обертки», особенно на объектах с классом «removeBtn».

$(this).parent('div').parent('div').remove();:

Представьте, что вы наводите порядок и хотите, чтобы что-то исчезло. В этой строке говорится: «Когда вы нажимаете кнопку «Удалить», весь ящик, содержащий ее, исчезает».

Отправка формы:

const submit = document.getElementById('submit');:

Это все равно, что привлечь внимание к чему-то под названием «отправить». Это кнопка, которая отправляет данные вашей формы.

submit.addEventListener('click', (e) =› { … });:

Теперь, когда вы нажимаете кнопку «Отправить», происходит нечто особенное. То, что находится внутри фигурных скобок {…} — это то, что делается.

const data = $(’#testform’).serializeArray();:

Представьте, что вы собираете всю информацию из формы в одну аккуратную стопку. Эта строка делает это и превращает информацию в список вещей.

const csrf = document.getElementsByName('csrfmiddlewaretoken');:

Это похоже на поиск секретного кода, который охраняет вашу форму. Это важно для безопасности.

Организация данных:

Эта часть похожа на просмотр списка вещей, которые вы собрали ранее. Вы проверяете каждую вещь и решаете, что с ней делать.

Подготовка к отправке:

var data = {};:

Представьте, что у вас есть специальный ящик для хранения вещей. Вот что такое «данные» — место для размещения всей важной информации. Проверка ответов: Если в поле есть ответы: Добавляем в поле секретный код. Мы помещаем вопрос и ответы в поле. Отмечаем правильный ответ и тоже кладем его в клеточку. Отправка запроса: это похоже на отправку сообщения. Там написано: «Эй, нам нужна помощь с сайта «/submit/». И вот все, что мы хотим отправить. Празднование успеха: когда сообщение доставлено, мы счастливы!

Мы кричим: «Привет, мир!» праздновать.

Вывод:

Наконец, записываем отправленное в специальный блокнот, который называется консолью. Это как вести дневник наших приключений. И вот оно — путешествие по миру Django, AJAX и jQuery. Вы стали свидетелем волшебства создания динамической формы, которая может добавлять, удалять и отправлять поля. Пусть эти знания станут вашим проводником в увлекательном мире веб-разработки!