yutamugiruru
@yutamugiruru (mui)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

flask sqlalchemyでのリスト形式の保存方法が分からないです。 

解決したいこと

flask sqlalchemyでリスト形式でデータベース保存・表示できるようにしたいです。
保存例:['東京都','石川県','神奈川県']
表示例:東京都
    石川県
    神奈川県

selectでmultipleな値をgetlistでPOSTした後、Flask-sqlalchemyのデータ格納ができません。
documentでの確認、ネットで解決方法を調べましたがどれも下記のエラーが発生して上手く動かないのでご教授頂きたいです。

発生している問題・エラー

sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 3 - probably unsupported type.

ソースコード(app.py)


from flask import Flask
from import render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_, or_, not_
from sqlalchemy.dialects import postgresql as pg

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///info.db'
db = SQLAlchemy(app)

#store table
class Store(db.Model):
    __tablename__ = 'stores'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    pref = db.Column(pg.ARRAY(db.String()), nullable=False, default=False)
    store_area = db.Column(db.String(30))

#store create
@app.route("/create", methods=['GET','POST'])
def create():
    if request.method == 'POST':
        #値を受け取る
        name = request.form['name']
        pref = request.form.getlist('pref')  
        store_area = request.form['area']

        storeList = Store(name = name, pref = pref, store_area = store_area)

        db.session.add(storeList)
        db.session.commit()

        return render_template('auth/create.html', store = storeList)

    else:
        return render_template("auth/create.html")

ソースコード(create.html, search.html)

<!--create.html入力画面-->

<form action="" enctype="multipart/form-data" method="POST">

    <label for="name">*必須:店舗名</label>
    <input type="text" name="name">

    <label for="pref">*必須:エリア(複数可)</label>
        <select name="pref" id="" multiple>
            <option value="北海道">北海道</option>
            <option value="青森県">青森県</option>
            <option value="岩手県">岩手県</option>
            <option value="宮城県">宮城県</option>
            <option value="秋田県">秋田県</option>
                         ........
    </select>

    <label for="store_area">店舗エリア</label>
    <input type="text" name="store_area" placeholder="OO店etc">

</form>

<!--search.html表示画面-->

<p>検索結果:{{ count }}件</p>

{% for store in store_all %}

    <article>
        <a href="{{store.id}}/detail">詳細</a>
        <h2>{{ store.name }}</h2>
        {% for i in store.pref %}
            <p>{{ i }}</p>
        {% endfor %}
        <p>{{ store.store_area }}</p>
    </article>

{% endfor %}

自分で試したこと

1.(app.py)結果:保存は解決しましたが、文字列型なので一文字づつ表示されます。

from flask import Flask
from import render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_, or_, not_

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///info.db'
db = SQLAlchemy(app)

#store table
class Store(db.Model):
    __tablename__ = 'stores'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    #変更点1
    pref = db.Column(db.String(), nullable=False, default=False)
    store_area = db.Column(db.String(30))

#store create
@app.route("/create", methods=['GET','POST'])
def create():
    if request.method == 'POST':
        #値を受け取る
        name = request.form['name']
        #変更点2
        pref = str(request.form.getlist('pref'))  
        store_area = request.form['area']

        storeList = Store(name = name, pref = pref, store_area = store_area)

        db.session.add(storeList)
        db.session.commit()

        return render_template('auth/create.html', store = storeList)

    else:
        return render_template("auth/create.html")

2.(app.py)結果:上記と同じInterfaceErrorが出ました。


from flask import Flask
from import render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_, or_, not_

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///info.db'
db = SQLAlchemy(app)

#store table
class Store(db.Model):
    __tablename__ = 'stores'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    #変更点
    pref = db.Column(Boolean(), nullable=False, default=False)
    store_area = db.Column(db.String(30))

#store create
@app.route("/create", methods=['GET','POST'])
def create():
    if request.method == 'POST':
        #値を受け取る
        name = request.form['name']
        pref = request.form.getlist('pref')  
        store_area = request.form['area']

        storeList = Store(name = name, pref = pref, store_area = store_area)

        db.session.add(storeList)
        db.session.commit()

        return render_template('auth/create.html', store = storeList)

    else:
        return render_template("auth/create.html")

Text型でも同じ結果となりました。
どうか宜しくお願い致します。

0

1Answer

元の app.py の

store_area = request.form['area']

で、 request.form['area'] は最初の area パラメータの値(例: '東京都')しか取得できません。エラーはこの文字列値を配列型のカラムに挿入しようとしているせいではないでしょうか。

area パラメータのすべての値をリストで取得するには以下のようにしてください。

store_area = request.form.getlist('area')
0Like

Comments

  1. @yutamugiruru

    Questioner

    ご回答ありがとうございます。
    areaの方はinputタグでこのままでも大丈夫なのですが、prefの方が保存出来ない状態です。
    カラムを変更するか、値の受け取り方を変更するか、もしくは両方なのか分からないです🙇‍♂️
  2. すみません、 pref と area を見間違えていました。 pref の方はすでに getlist で取得していましたね。
  3. pg.ARRAY を使っているのでデータベースは PostgreSQL なのかと思いましたが、 SQLite3 のようですね。 SQLite3 は配列型カラムに対応していないので pref をそのまま格納することはできません。 TEXT 型カラムを用意して、 json.dumps(pref) で作った JSON 文字列を格納してください。
  4. @yutamugiruru

    Questioner

    何度もご回答ありがとうございます。
    ほぼほぼ答えに近づきましたので後は自分で辿り着こうと思います。
    ありがとうございました!

Your answer might help someone💌