59894


**実現したいこと**  
FlaskとSQLAlchemy、JSONを使って、Webアプリケーションを作成しています。  
フォームに入力された文字列をデータベースに格納し、HTMLで書いたページにも表示しようとしています。

**困っていること**  
エラーが出てどのように解決すればいいのか見当がつきません。

エラー文

[code]

    $ FLASK_APP=app.py FLASK_DEBUG=true flask run
     * Serving Flask app "app.py" (lazy loading)
     * Environment: production
       WARNING: Do not use the development server in a production environment.
       Use a production WSGI server instead.
     * Debug mode: on
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
     * Restarting with stat
    /Users/username/.pyenv/versions/3.6.0/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py:835: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
      'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
     * Debugger is active!
     * Debugger PIN: 232-439-885
    /Users/username/.pyenv/versions/3.6.0/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py:835: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
      'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
    127.0.0.1 - - [23/Oct/2019 10:51:00] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [23/Oct/2019 10:51:01] "GET /favicon.ico HTTP/1.1" 404 -
    (<class 'AttributeError'>, AttributeError("'ImmutableMultiDict' object has no attribute 'get_json'",), <traceback object at 0x10517fcc8>)
    127.0.0.1 - - [23/Oct/2019 10:51:05] "POST /todos/create HTTP/1.1" 400 -
    
[/code]

**実行しているプログラム**  
App.py

[code]

    from flask import Flask, render_template, request, redirect, url_for, abort
    from flask_sqlalchemy import SQLAlchemy
    import sys
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://username@localhost:5432/todoappbegin'
    db = SQLAlchemy(app)
    
    class Todo(db.Model):
        __tablename__ = 'todos'
        id = db.Column(db.Integer, primary_key=True)
        description = db.Column(db.String(), nullable=False)
    
        def __repr__(self):
            return f'<Todo {self.id}{self.description}>'
    
    db.create_all()
    
    @app.route('/todos/create', methods=['POST'])
    def create_todo():
      error = False
      body = {}
      try:
        description = request.form.get_json()['description']
        todo = Todo(description=description)
        db.session.add(todo)
        db.session.commit()
        body['description'] = todo.description
      except:
        error = True
        db.session.rollback()
        print(sys.exc_info())
      finally:
        db.session.close()
      if error:
        abort (400)
      else:
        return jsonify(body)
    
    @app.route('/')
    def index():
        return render_template('index.html', data=Todo.query.all())
    
[/code]

Index.html

[code]

    <html>
    <head>
        <title>Todo App</title>
    <style>
        .hidden{
            display:  none;
        }
    </style>
    </head>
    <body>
        <form method="post" action="/todos/create">
            <input type= "text" name="description" />
            <input type= "submit" value="Create" />
        </form>
        <div id= "error" class="hidden">Something went wrong!</div>
        <ul>
            {% for d in data %}
            <li>{{d.description}}</li>
            {% endfor %}
        </ul>
        <script>
          const descInput = document.getElementById('description');
          document.getElementById('form').onsubmit = function(e) {
            e.preventDefault();
            const desc = descInput.value;
            descInput.value = '';
            fetch('/todos/create', {
              method: 'POST',
              body: JSON.stringify({
                'description': desc,
              }),
              headers: {
                'Content-Type': 'application/json',
              }
            })
            .then(response => response.json())
            .then(jsonResponse => {
              console.log('response', jsonResponse);
              li = document.createElement('li');
              li.innerText = desc;
              document.getElementById('todos').appendChild(li);
              document.getElementById('error').className = 'hidden';
            })
            .catch(function() {
              document.getElementById('error').className = '';
            })
          }
        </script>
    </body>
    </html>
    
[/code]

**試したこと**  
Postgresで確認したところ、

[code]

    class Todo(db.Model):
        __tablename__ = 'todos'
        id = db.Column(db.Integer, primary_key=True)
        description = db.Column(db.String(), nullable=False)
    
        def __repr__(self):
            return f'<Todo {self.id}{self.description}>'
    
    db.create_all()
    
[/code]

部分のテーブル作成には成功していることがわかりましたが入力データは入っていないようです。

[code]

    # \dt
           List of relations
     Schema | Name  | Type  | Owner 
    --------+-------+-------+-------
     public | todos | table | username
    (1 row)
    
    # select * from todos;
     id | description 
    ----+-------------
    (0 rows)
    
[/code]

**実行環境**  
Python 3.6.0  
Flask 1.1.1  
Sqlalchemy 1.3.10  
psql (PostgreSQL) 11.5  
ブラウザ Google Chrome


CC BY-SA 4.0
2019-10-23T02:10:57.180
59893
2019-10-23T02:20:56.313
question
python json postgresql flask sqlalchemy
Flaskでフォームから入力された値がデータベースに格納されずページにも表示されない


> (, AttributeError("'ImmutableMultiDict' object has no attribute
> 'get_json'",), )  
>  127.0.0.1 - - [23/Oct/2019 10:51:05] "POST /todos/create HTTP/1.1" 400 -

コード内の以下の部分を探してください。

[code]

    description = request.form.get_json()['description']
    
[/code]

`request.form`は`ImmutableMultiDict`であり、`get_json`という関数は持っていません。以下のように修正してください。

[code]

    description = request.form['description']
    
[/code]


CC BY-SA 4.0
2019-10-23T02:20:56.313
59894
2019-10-23T02:20:56.313
59893
answer