【问题标题】:Keyerror when doing a json post request on sqlalchemy在 sqlalchemy 上执行 json 发布请求时出现键错误
【发布时间】:2021-04-05 17:29:58
【问题描述】:

我正在为一个必须编辑入门代码的课程项目工作。我不断收到 KeyError 代码,但我不确定是什么问题。

第 250 行,在 create_venue_submission 中 name = request.get_json()['name'] KeyError:'名称'

下面的代码来自 new_venue.html

我为所有 div 添加了 id="name"、city 等。我不确定这是否是正确的方法,但这是我想从表单中提取所有数据的唯一方法。

   {% extends 'layouts/main.html' %}
{% block title %}New Venue{% endblock %}
{% block content %}
  <div class="form-wrapper">
    <form id="venueInfo" method="post" class="form">
      <h3 class="form-heading">List a new venue <a href="{{ url_for('index') }}" title="Back to homepage"><i class="fa fa-home pull-right"></i></a></h3>
      <div id='name' class="form-group">
        <label for="name">Name</label>
        {{ form.name(class_ = 'form-control', autofocus = true) }}
      </div>
      <div class="form-group">
          <label>City & State</label>
          <div class="form-inline">
            <div id='city' class="form-group">
              {{ form.city(class_ = 'form-control', placeholder='City', autofocus = true) }}
            </div>
            <div id='state' class="form-group">
              {{ form.state(class_ = 'form-control', placeholder='State', autofocus = true) }}
            </div>
          </div>
      </div>
      <div id='address' class="form-group">
        <label for="address">Address</label>
        {{ form.address(class_ = 'form-control', autofocus = true) }}
      </div>
      <div id='phone_num' class="form-group">
          <label for="phone">Phone</label>
          {{ form.phone(class_ = 'form-control', placeholder='xxx-xxx-xxxx', autofocus = true) }}
        </div>
      <div id="genres" class="form-group">
        <label for="genres">Genres</label>
        <small>Ctrl+Click to select multiple</small>
        {{ form.genres(class_ = 'form-control', autofocus = true) }}
      </div>
      <div id="fb_link" class="form-group">
          <label for="genres">Facebook Link</label>
          {{ form.facebook_link(class_ = 'form-control', placeholder='http://', autofocus = true) }}
        </div>
      <input type="submit" value="Create Venue" class="btn btn-primary btn-lg btn-block">
    </form>

    <script type="text/javascript">

      document.getElementById("venueInfo").onsubmit=function(e){
        e.preventDefault();
        fetch('/venues/create',{
        method:'POST',
        body:JSON.stringify({
          'name': document.getElementById('name').value,
          'city': document.getElementById('city').value,
          'state': document.getElementById('state').value,
          'address': document.getElementById('address').value,
          'phone_num': document.getElementById('phone_num').value,
          'genres': document.getElementById('genres').value,
          'fb_link': document.getElementById('fb_link').value,
      }),
        headers: {'Content-type': 'application/json'}
      })
      .then(function(){
      })
    }

    </script>


  </div>

{% endblock %}
    

以下代码来自 app.py

@app.route('/venues/create', methods=['GET'])
def create_venue_form():
  form = VenueForm()
  return render_template('forms/new_venue.html', form=form)

    @app.route('/venues/create', methods=['POST'])
def create_venue_submission():
  name = request.get_json()['name']
  print(name)

  flash('Venue ' + request.form['name'] + ' was successfully listed!')

  return render_template('pages/home.html')

【问题讨论】:

    标签: json ajax flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    看起来您正在使用 Flask-WTF 来制作这些表单字段,然后使用 JS 函数通过 getElementById 从这些字段中获取值。

    问题是您没有在表单字段上设置id。要获得更好的可视化效果,请查看呈现的 HTML,而不是模板代码本身。

    所以而不是:

    {{ form.name(class_ = 'form-control', autofocus = true) }}
    

    你正在寻找类似的东西:

    {{ form.name(id='name', class_ = 'form-control', autofocus = true) }}
    

    然后验证渲染为:

    <input autofocus class="form-control" id="name" name="name" type="text" value="">
    

    请注意,这现在有一个 id 属性,它应该允许您的 JS 函数获取值。

    您需要将同样的概念应用到其他表单字段。

    我为所有 div 添加了 id="name"、city 等。我不确定这是否是正确的方法,但这是我想从表单中提取所有数据的唯一方法。

    divs 这样做是没有用的...document.getElementById('name').value 采用输入字段的值,所以这就是您必须添加id 属性的内容,如上所述。

    编辑评论

    在您的create_venue_submission 路由中,request.get_json 方法接收由 javascript Fetch 请求提交的值。另一方面,request.form 包含不使用 Javascript 提交表单时的值。

    使用 Javascript 方法:e.preventDefault() 防止在单击按钮时进行传统的表单提交,而是提交带有标题 {'Content-type': 'application/json'} 的 Fetch 请求。

    通过删除该脚本标记,或者在禁用了 javascript 的浏览器中运行,它将退回到传统的提交方法。

    所以你可能应该在你的烧瓶路线中做一些逻辑来测试这种情况。您也可以为此使用request.is_json boolean。记得做from flask import jsonify。比如:

    if request.is_json:
    
        # Request came in via javascript based on the header provided.
    
        name = request.get_json()['name']
    
        # Add data to database or something
    
        return jsonify({'message':f'{name} was sucessfully listed.'})
    
    else:
        # handle traditional form submission
        
        name = request.form['name']
        
        # Add data to database or something
    
        flash('Venue ' + request.form['name'] + ' was successfully listed!')
        return render_template('pages/home.html')
    

    当然你需要在你的前端handle the returned JSON。因此:

    .then(function(){
          })
    

    类似:

    .then(response => response.json())
    .then(data => {
        console.log(data);
    });
    

    现在打开浏览器的开发工具控制台,您在提交时应该会看到如下内容:

    Object { message: "Burning Man Festival was sucessfully listed." }
    

    当然,然后您可以将 console.log 换成任何东西来操作 dom,并访问例如 data['message'] 以获取成功字符串本身。

    【讨论】:

    • 谢谢,成功了!由于某种原因,一旦我这样做了,就会发生其他事情。 {flash('Venue ' + request.form['name'] + ' 已成功列出!') return render_template('pages/home.html')} 没有做任何事情。这意味着如果我从 .html 中删除脚本部分,该页面通常会转到主页并显示已创建场所 x。但是一旦我有了获取脚本,当我点击创建场所时,什么都没有发生。
    猜你喜欢
    • 1970-01-01
    • 2019-02-01
    • 2016-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 2020-06-30
    • 2021-03-02
    相关资源
    最近更新 更多