将字典从javascript函数传递到python函数:始终为无

2024-04-25 04:53:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我们正在使用Flask创建一个web应用程序。在一个html页面上,用户回答一些问题(使用<form>)。在此过程中,当他们收到随机弹出通知时,会要求他们在页面上单击按钮几次。在.html文件中,我们编写javascript函数将用户单击按钮的时间戳保存到数组中

我们希望存储用户的答案和单击按钮的时间戳。现在从.html.py,我们使用request.form传递答案,并使用ajax json(request.json)传递时间戳数组。request.form运行得很好,但是request.json总是给出一个None。我们已经尝试过{}、{}、{},但没有一个有效

我们的代码如下:

trial.py中:

from flask import (Blueprint, flash, g, redirect, render_template, request, url_for, jsonify, json)
from werkzeug.exceptions import abort
import csv
from flaskr.db import get_db

bp = Blueprint('trial', __name__, url_prefix='/trial')

@bp.route('', methods=('GET', 'POST'))
def trial():
    if request.method == 'POST':
        if "Q1" in request.form:
            ## this part retrieves data from request.form 
            ## skip the details in the following
            db = get_db()
            db.execute(
                    'INSERT INTO trial (...)', (...))
            db.commit()

        timestamps = request.json
        print(timestamps)  ### This is always a None

   return render_template('study/trial.html')

trial.html中:

{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}Trial{% endblock %}</h1>
{% endblock %}

{% block content %}

  <!-- Skip non-related details in the following --> 
  <button class="NotificationButton" onclick="popup()">I Got A Notification</button>

  <div>
    <form name="TrialQuestions" id="TrialQuestions" method="post">
      <!-- skip the details of the questions and input for answers -->                                             
    </form>
  </div>

  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script>window.jQuery || document.write('<script src="{{url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
  
  <script>
    var timestamps = {"trial":[]};

    function playAudio() { 
      <!-- skip non-related details -->
      timestamps["trial"].push(remaining);
    } 

    function popup(){
      <!-- skip non-related details -->
      timestamps["trial"].push(remaining);
    }

    function timeUp(){
      document.TrialQuestions.submit();
      $.ajax({
        type: "POST",
        url: "{{ url_for("trial.trial") }}",
        contentType: "application/json",
        data: JSON.stringify(timestamps),
        dataType: "json",
        success: function(response) {
        console.log(response);
        },
        error: function(err) {
        console.log(err);
        }
      });
      alert("Time Is Up! Your Answers Have Been Submitted!");
    }

  </script>
{% endblock %}

{}中的{}运行良好,但是{}中的{}总是给出一个{}。我们已经搜索并尝试了以下帖子中的建议,但没有一个能解决问题:

  1. Passing Javascript array in Python Flask
  2. Get the data received in a Flask request
  3. How to send information from javascript to flask route

有人能给点提示吗?非常感谢


Tags: theinfromformjsonurldbrequest
2条回答

。。。更新我自己的问题

如问题中所述,request.form可以工作,但request.json将给出“无”

按照Detlef的方法,根据我自己的尝试,request.json可以工作,但request.form将给出一个“无”。如果我弄错了什么,请纠正我

因此,现在我提出了一种折衷方法:将表单和时间戳打包到一个ajax JSON对象中。代码如下所示:

  <div>
    <form name="TrialQuestions" id="TrialQuestions">  
      <label for="Q1">Question 1</label>
      <input name="Q1" id="Q1"> 
      <!  skip the questions  >                                              
    </form>
  </div>

  <script>
  var TrialQuestionAnswers = [];
  var timestamps = [];
  var formAndTimestamps = [];
  
  function timeUp(){
      TrialQuestionAnswers = [document.getElementById("Q1").value, ..., document.getElementById("Q13").value];
      formAndTimestamps.push(TrialQuestionAnswers);
      formAndTimestamps.push(timestamps);

      $.ajax({
        type: "POST",
        url: "{{ url_for("trial.trial") }}",
        contentType: "application/json",
        data: JSON.stringify(formAndTimestamps),
        dataType: "json",
        success: function(response) {
        console.log(response);
        },
        error: function(err) {
        console.log(err);
        }
      });
      alert("Time Is Up! Your Answers Have Been Submitted!");
    }
  </script>

它可以工作,但也许这不是最有效的解决方案。更好的主意是非常感谢

表单提交会导致页面被重新加载,并且模板会作为html从服务器再次传输

异步javascript请求仅在调用成功或错误回调时结束。不等待数据的传输

function timeUp() {
  console.log("sending data to " + "{{ url_for('trial.trial') }}")

  $.ajax({
    type: "POST",
    url: "{{ url_for('trial.trial') }}",
    contentType: "application/json",
    data: JSON.stringify(timestamps),
    dataType: "json",
    success: function(response) {
      console.log(response);
      // The data has now been successfully transferred.
      
      // document.TrialQuestions.submit();
    },
    error: function(err) {
      console.log(err);
    }
  });
}

当指定数据类型时,查询期望的答案正好是这个。另见here
因此,我将返回json格式的响应

from flask import render_template, request, jsonify

@bp.route('/', methods=('GET', 'POST'))
def trial():
    if request.method == 'POST':
        print('got a post request')

        if request.is_json: # application/json
            # handle your ajax request here!
            print('got json:', request.json)
            return jsonify(success=True) # answer as json
        else: 
            # handle your form submit here!
            print(request.form)
    return render_template('trial.html')

AJAX的优点是,您可以发送和加载数据集,而无需重新加载和呈现整个页面

在传输中,数据以预定义格式格式化。提交表单时,使用类型“application/x-www-form-urlencoded”或“multipart/form data”。对于JSON,它是“应用程序/JSON”。
根据所选格式,查询“request.json”返回“None”或“request.form”为空字典

数据集的结构取决于您的需求。
下面是一个类似于表单原始方法的建议

function timeUp() {
  const data = {
    "data": $("form[name='TrialQuestions']").serializeArray().map(elem => {
      return [elem["name"], elem["value"]];
    }),
    "ts": timestamps,
  };

  $.ajax({
    type: "POST",
    url: "{{ url_for('trial.trial') }}",
    contentType: "application/json",
    data: JSON.stringify(data),
    dataType: "json",
    success: function(response) {
      console.log(response);
    },
    error: function(err) {
      console.log(err);
    }
  });
}

您是否只想发送表单,例如,因为您想执行重定向。在表单中添加一个或多个隐藏字段,并在提交前填写其值

<form name="TrialQuestions" method="post">
  <label for="q1">Question 1</label>
  <input name="q1" id="q1" value="a1" />
  <input name="ts" type="hidden" />
</form>

<script>
  function timeUp() {
    document.forms["TrialQuestions"]["ts"].value = timestamps.join();
    document.forms["TrialQuestions"].submit();
  }
</script>

相关问题 更多 >