Онлайн ожидание: 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})
Вернуться на верх