Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

javascript - Django/Js: how to post a form without reloading whole page

My application currently flows through 3 pages:

  1. User selects question in index page
  2. User submits answer in answer page
  3. User is presented with result in results page.

I want to compress that down to a single page where the user submits an answer to the question and result is shown on the same page.

The following django-template code separates questions with Bootstrap accordion. How do I post the form without refreshing the whole page? I want to be able to display the result on the page, update CSS styling with Javascript etc.

<h2>{{ category.title }}</h2>
    <div class="accordion" id="accordion{{category.title}}">

      {% for challenge in category.challenge_set.all %} 
      <div class="card">
        <div class="card-header" id="heading{{challenge.id}}">
          <h2 class="mb-0">
            <button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapse{{challenge.id}}" aria-expanded="true" aria-controls="collapse{{challenge.id}}">
              {{ challenge.question_text }} - {{ challenge.point_value }} points
            </button>
          </h2>
        </div>
        <div id="collapse{{challenge.id}}" class="collapse in" aria-labelledby="heading{{challenge.id}}" data-parent="#accordion{{category.title}}">
          <div class="card-body">
            
            <p>{{ challenge.description }}</p>
          
            <form action="{% url 'challenges:answer' challenge.id %}" method="post">
            
              {% if challenge|is_answered:request %}
                <label for="answered">Answer</label>
                <input type="text" name="answered" id="answered" value="{{ challenge.answer_text }}" readonly>
              {% else %}
              {% csrf_token %}
                <label for="answer">Answer</label>
                <input type="text" name="answer" id="answer">
                <input type="submit" value="Submit">
              {% endif %}
            </form>
        </div>
      </div>
      {% endfor %}

    </div>

Here is the view:

def index(request):
    context = {'challenges_by_category_list': Category.objects.all()}
    return render(request, 'challenges/index.html', context)

def detail(request, challenge_id):
    challenge = get_object_or_404(Challenge, pk=challenge_id)
    return render(request, 'challenges/detail.html', {'challenge': challenge})

def results(request, challenge_id, result):
    challenge = get_object_or_404(Challenge, pk=challenge_id)
    return render(request, 'challenges/results.html', {'challenge':challenge, 'result':result})

def answer(request, challenge_id):
    challenge = get_object_or_404(Challenge, pk=challenge_id)
    result = "Incorrect, try again!"
    if challenge.answer_text.lower() == request.POST['answer'].lower():
      current_user = request.user
      session = User_Challenge(user=current_user, challenge=challenge, answered=True)
      session.save()
      points = Profile(user=current_user, points=challenge.point_value)
      points.save()
      result = "Correct!"
    return HttpResponseRedirect(reverse('challenges:results', args=(challenge.id, result)))
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can try this:

Add the below script in your template:

<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

write a script and a function inside it to submit the form data.

<script type="text/javascript">
    function submitData( challenge_id ){
        // Get answer from the input element
        var answer = document.getElementById("answer").value;

        // add the url over here where you want to submit form & challenge_id is also taken as a parameter.
        var url = "<your_url>";

        $.ajax({
            url: url,
            data: {
                'answer': answer,
            },
            dataType: 'JSON',
            success: function(data){
                // show an alert message when form is submitted and it gets a response from the view where result is provided and if url is provided then redirect the user to that url.
                alert(data.result);
                if (data.url){
                   window.open(data.url, '_self');
                }
            }
        });
    }
</script>

Change type of the submit button and add an onclick event to call the submitData() function and pass the challenge id to it. And remove the action attr from the form. see below:

<form method="post">
    {% csrf_token %}
    {% if challenge|is_answered:request %}
        <label for="answered">Answer</label>
        <input type="text" name="answered" id="answered" value="{{ challenge.answer_text }}" readonly>
    {% else %}
        <label for="answer">Answer</label>
        <input type="text" name="answer" id="answer">
        // over here
        <button type="button" onclick="submitData({{ challenge.id }})">
            Submit
        </button>
    {% endif %}
</form>

Return a JsonReponse to the ajax call from the views.

views.py

def answer(request, challenge_id):
    answer = request.GET.get('answer', False)
    url = False
    if challenge.objects.filter(id=challenge_id).exists() and answer:
       challenge = Challenge.objects.get(id=challenge_id)
       if challenge.answer_text.lower() == answer.lower():
          current_user = request.user
          session = User_Challenge(user=current_user, challenge=challenge, answered=True)
          session.save()
          points = Profile(user=current_user, points=challenge.point_value)
          points.save()
          result = "Correct!"
  
          # specify the url where you want to redirect the user after correct answer
          url = "" 
    else:
       result = "Incorrect, try again!"
    data = {
       'result': result,
       'url': url
    }
    return JsonResponse(data)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...