Онлайн ожидание: django отправка формы и отображение результата на одной странице
У меня есть срочная задача сделать веб-страницу, которая позволяет пользователю вводить некоторые данные, а бэкенд делает некоторые вычисления, и результат должен отображаться на той же странице чуть ниже поля ввода (как проверка цены авиабилета онлайн).
Я новичок в django и html. ниже приведена моя первая тестовая веб-страница простого онлайн-калькулятора, чтобы попытаться понять, как сделать такой веб-сервис.
Я обнаружил проблему, что при нажатии кнопки "submit" происходит переход на новую веб-страницу или новую веб-вкладку. это не то, что я хочу. Когда пользователь вводит данные и нажимает кнопку "отправить", я хочу, чтобы поле "результат" на странице непосредственно показывало результат (т.е. частично обновляло только это поле) без обновления/перехода на новую страницу. Также я хочу, чтобы введенные пользователем данные оставались на той же странице после нажатия кнопки "submit".
Я видел, что есть несколько различных способов сделать эту работу, iframe/AJAX. Однако, я искал/пытался найти ответы и решения в течение нескольких дней, и ни один из ответов действительно не работает для этого очень базового простого вопроса!!!
html:
<form method="POST">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div>{{ result }}</div>
<button type="submit">Submit</button>
</form>
view.py
def post_list(request):
result = 0
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
print(request.POST)
print(result)
context = {
'result': result
}
return render(request, 'blog/post_list.html', context)
Я бы предложил взглянуть на htmx.org, который делает это действительно простым без необходимости писать какой-либо фактический JS.
Для вашего примера:
(1) Вы добавляете htmx JS (который занимает всего около 10k) в HTML, и используете hx-post
и hx-target
для запуска ajax вызовов на вашей форме. С их помощью форма выполнит AJAX-запрос, а hx-target
скажет htmx взять ответ (который должен быть только результатом вычислений) и поместить его в div без обновления всей страницы.
Смотрите docs для более подробной информации об этом.
Заметьте также, что я указал id
на div, содержащий результат.
<html>
<body>
<form method="POST" hx-post="/post_list" hx-target="#result">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div id="result">{{ result }}</div>
<button type="submit">Submit</button>
</form>
<script src="https://unpkg.com/htmx.org@1.6.1"></script>
</body>
</html>
(2) По вашему мнению, вы определяете, является ли запрос AJAX-запросом от htmx, проверяя заголовки, и в этом случае вы хотите вернуть только результат. Есть более простые или элегантные способы сделать это (например, проверить django-htmx
, но для простоты:
from django.http.response import HttpResponse
from django.shortcuts import render
# Create your views here.
def post_list(request):
result = 0
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
if request.headers.get('Hx-Request') == 'true':
# return only the result to be replaced
return HttpResponse(str(result))
else:
return render(request, 'blog/post_list.html', {'result': result})