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"
>