【问题标题】:Django/Js: how to post a form without reloading whole pageDjango/Js:如何在不重新加载整个页面的情况下发布表单
【发布时间】:2021-03-11 03:38:32
【问题描述】:

我的应用程序目前流经 3 个页面:

  1. 用户在索引页面中选择问题
  2. 用户在回答页面提交回答
  3. 用户会在结果页面中看到结果。

我想将其压缩到一个页面,用户在该页面上提交问题的答案,结果显示在同一页面上。

以下django-template 代码使用 Bootstrap 手风琴分隔问题。如何在不刷新整个页面的情况下发布表单?我希望能够在页面上显示结果,使用 Javascript 更新 CSS 样式等。

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

这里是视图:

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

【问题讨论】:

  • 你可以使用ajax来做到这一点。如果您可以分享提交表单的视图,我可以向您展示如何做到这一点。

标签: javascript django twitter-bootstrap django-templates


【解决方案1】:

你可以试试这个:

在您的模板中添加以下脚本:

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

在其中编写一个脚本和一个函数来提交表单数据。

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

更改提交按钮的类型并添加 onclick 事件以调用 submitData() 函数并将挑战 ID 传递给它。并从表单中删除操作 attr。 见下文:

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

从视图返回一个 JsonReponse 给 ajax 调用。

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-02
    • 2010-12-22
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    相关资源
    最近更新 更多