Home > other >  Online waiting: django submit form and display result in same page
Online waiting: django submit form and display result in same page

Time:01-03

I have an emergent task to make a web page which allow user to input some data and the backend do some calculation and the result needs to be displayed in the same page just below the input field (like air ticket online price check).

I am new to django and html. below is my first test web page of a simple online calculator to try to figure out how to make such web service.

I found a problem that when clicking the "submit" button, it tends to jump to a new web page or a new web tab. this is not what I want. Once the user input the data and click "submit" button, I want the "result" field on the page directly show the result (i.e. partially update only this field) without refresh/jump to the new page. Also I want the user input data kept in the same page after clicking "submit".

I saw there might be several different ways to do this work, iframe/AJAX. However, I have been searching/trying for answers and solutions for several days and none of the answers really work for this very basic simple question!!

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)

CodePudding user response:

I would suggest taking a look at htmx.org which makes this really simple without having to write any actual JS.

For your example:

(1) You add the htmx JS (which is only about 10k) to your HTML, and use hx-post and hx-target to trigger the ajax calls on your form. With these the form will fire an AJAX request, and the hx-target tells htmx to take the response (which you want to be only the result of your calculation) and put it in the div without refreshing the whole page. See docs for more details on this. Note also I gave an id to the div containing the result. You will need to replace hx-post="{% url 'blog:post_list' %}" with the correct name to your view (which we don't know as you didn't post your urls.py).

<html>
    <body>
        <form method="POST" hx-post="{% url 'blog: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/[email protected]"></script>
    </body>
</html>

(2) In your view then you determine if the request is an AJAX request from htmx by checking the headers, in which case you want to only return the result. There are easier or elegant ways to do this (eg. check django-htmx, but just to keep it simple:

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})
  • Related