DJANGO Дублирование HTML при загрузке страницы

Я использую DJANGO для создания сайта с минимальным количеством дополнений. На данный момент у меня есть страница, которая дублирует себя при изменении выбора. Попытки изменить ее поведение только ухудшают ситуацию, например, если я меняю swap на outer, то она дублируется вне элемента, а не в нем.

Окружающая среда:

Windows 11 Pro x64
Visual Studio Code x64
python 3.12.3
Packages                  Versions
------------------------ ---------
asgiref                  3.8.1
certifi                  2025.1.31
charset-normalizer       3.4.1
Django                   5.2
django-htmx              1.23.0
django-multiselectfield  0.1.13
django-phonenumber-field 8.1.0
idna                     3.10
phonenumberslite         9.0.3
pip                      24.0
pyasn1                   0.6.1
pyasn1_modules           0.4.2
python-ldap              3.4.4

Базовый html:

{% load django_htmx %}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="keywords" content="HTML, CSS, Python, JINJA"/>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        {% htmx_script %}
    </head>
    <bod hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
        <div id="navbar">
            <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
                <span ><h1>{% block page_title %}base_title{% endblock page_title %}</h1></span>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbar" >
                    <div class="navbar-nav" style="margin-left: auto; margin-right: 0;">
                        <a class="nav-item nav-link" id="logout" href="/mytickets">
                            My Tickets
                        </a>
                        <a class="nav-item nav-link" id="logout" href="/createticket">
                            Create Ticket
                        </a>
                        <a class="nav-item nav-link" id="logout" href="/companytickets">
                            Company Tickets
                        </a>
                        <a class="nav-item nav-link" id="logout" href="/companyalerts">
                            Company Alerts
                        </a>
                        <a class="nav-item nav-link" id="logout" href="/logout">
                            Logout
                        </a>
                        <a class="nav-item nav-link" id="logout" href="/profile">
                            <svg xmlns="../static/css/person.svg" width="16" height="16" fill="black" class="bi bi-person" viewBox="0 0 16 16">
                                <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6m2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0m4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4m-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10s-3.516.68-4.168 1.332c-.678.678-.83 1.418-.832 1.664z"/>
                              </svg>
                        </a>
                    </div>
                </div>
            </nav>
        </div>
        {% block select %} base_select {% endblock select%}
        {% block content %} base_content {% endblock content %}
    </body>
</html>

Шаблон для:

{% extends 'website/base.html' %} 

{% block page_title %}
    Create Tickets
{% endblock %}
{% block select %}
    <select hx-post="/createticket/" hx-swap="innerHTML" hx-trigger="change" hx-target="#form-content" selected="other" name="select_ticket_type" id="select_ticket_type">
        <option value="new_user">New Employee</option>
        <option value="new_asset">New Asset</option>
        <option value="new_app">New Application</option>
        <option value="other">Other</option>
    </select> 
{% endblock select %}
{% block content %} 
    <form name="form-content" id="form-content" method="post">
        {% csrf_token %}
        {{ form }}
        <button type="submit" name="Create Ticket">Create Ticket</button>
    </form>
{% endblock content %}

Вид.py:

def create_ticket(response):
    form_selection = response.POST.get('select_ticket_type')
    print(response)
    if response.method == "POST":
        match form_selection:
            case "new_user":
                print("new user")
                new_user = CreeateUser(response.POST)
                if new_user.is_valid():
                    # Process form A data
                    response.session['display_form'] = response.POST.get('select_ticket_type')
                    return redirect('createticket')
            case "new_app":
                print("new app")
                new_app = CreateApplication(response.POST)
                if new_app.is_valid():
                    # Process form B data
                    response.session['display_form'] = response.POST.get('select_ticket_type')
                    return redirect('my_view')
            case "new_asset":
                print("new asset")
                new_asset = CreateAsset()
                if new_asset.is_valid():
                    # Process form B data
                    response.session['display_form'] = response.POST.get('select_ticket_type')
                    return redirect('my_view')
            case _:
                print("other")
                form = CreateOther(response.POST)
    display_form = response.session.get('display_form', response.POST.get('select_ticket_type'))
    print(f"display for is {display_form}")
    match display_form:
        case "new_user":
            print("Form is for user")
            form = CreeateUser()
        case "new_app":
            print("form is for app")
            form = CreateApplication()
        case "new_asset":
            print("form for new asset")
            form = CreateAsset()
        case _:
            form = CreateOther()

    context = {'form': form}
    return render(response, 'website/createticket.html', context)

Я постарался сделать его как можно более простым, чтобы уменьшить количество конфликтов и сузить область поиска. hx-swap «outer/innter/beforebegin/afterbeing/...» не помогает.

Я написал AJAX для этого, и он делает то же самое.

       const select_ticket_type = document.getElementById('select_ticket_type');
        select_ticket_type.addEventListener('change', function() {
            const selectedValue = this.value;
            fetch('/createticket/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'X-CSRFToken': '{{ csrf_token }}', 
                },
                body: 'select_ticket_type=' + selectedValue, 
            })
            .then(response => response.text())
            .then(data => {                
                document.getElementById('form-content').innerHTML = data;
            });
           
        });

Проблема в том, что при выборе вы заменяете <form name="form-content" id="form-content" method="post"> на всю страницу целиком.

Что вы на самом деле хотите сделать, так это заменить содержимое формы содержимым вновь созданной формы и игнорировать остальную часть страницы.

В Html есть атрибут для достижения этой цели, hx-select. Документы здесь.

Чтобы использовать его, добавьте hx-select="#form-content" к выбранному вами тегу:

<select 
    hx-post="/createticket/" 
    hx-swap="innerHTML" 
    hx-trigger="change" 
    hx-target="#form-content" 
    hx-select="#form-content" 
    selected="other" 
    name="select_ticket_type" 
    id="select_ticket_type"
    >
Вернуться на верх