質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

1371閲覧

flask-SQLAlchemyで作ったモデルの上書きができない(enum.Enumを利用したenum型の名称変更)

baboo

総合スコア8

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/06/03 15:25

編集2021/06/04 11:51

Flaskを学習中のものになります。
下記のようにモデルを定義し、テーブルを作成した後、

Pyhon

1# define Models 2class SexType(enum.Enum): 3 men = 'men' 4 women = 'women' 5 other = 'other' 6 7class User(db.Model): 8 __tablename__ = 'users' 9 id = db.Column(db.Integer, primary_key = True) 10 username = db.Column(db.String(64), unique = False) 11 age = db.Column(db.Integer) 12 sex = db.Column(db.Enum(SexType))

Shell

1from app import db 2db.create_all()

enumで取りうる値をmen→man、women→womanへと変更したいと思い、

Pyhon

1# define Models 2class SexType(enum.Enum): 3 man = 'man' 4 woman = 'woman' 5 other = 'other' 6 7class User(db.Model): 8 __tablename__ = 'users' 9 id = db.Column(db.Integer, primary_key = True) 10 username = db.Column(db.String(64), unique = False) 11 age = db.Column(db.Integer) 12 sex = db.Column(db.Enum(SexType))

として、テーブルを削除した上でpsqlコマンドでコンソールからPostgreSQL環境へログインし、
作成したテーブルを削除した後、
flask shellよりdb.create_all()をして、再度テーブルを作成しましたが、enumで取りうる値が変わりません。
ただclass SexTypeをclass SexType2など名称を変更すれば無事変更ができます。

どこかにキャッシュでも残り、うまく上書きできていないのでしょうか?
お力お貸しいただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2021/06/03 23:08

> 下記のようにモデルを定義し、テーブルを作成した後、 > テーブルを削除した上で再度同じ手順を繰り返しても このあたり、何をしたのかが伝わってません。
baboo

2021/06/04 11:49

こちら失礼いたしました! psqlコマンドでコンソールからPostgreSQL環境へログインし、 作成したテーブルを削除した後、 flask shellよりdb.create_all()をして、再度テーブルを作成しました!
退会済みユーザー

退会済みユーザー

2021/06/04 23:53 編集

何が出来て何が出来ていないのか明確な操作手順がなく、他人が判断できないのではないかと思います。 難しいとは思いますが、回答者から聞かれて始めて答える内容がないように、予め聞かれそうなことは網羅して書かないと、誰も相手をしてくれない可能性が高いです。 誰もが常に暇なわけではなく、書き込みをしてる間だけ時間が取れているはずなので、何度もやり取りが発生しそうな質問は自ずと避けがちです。 なので、他の人が全く同じことをして簡単に再現できる手順を書くように心がけてください。 今回でいうと、PostgreSQLを使ってる時点でアウトでしょうね。 簡単なことなので、まずはsqlite3で始めましょう。 環境の説明も必要です。再現できることを前提に例えば以下のように環境を作成します。 $ python -m venv env # 環境によってはpython3とかかも $ . env/bin/activate # windowsなら.\env\Scripts\Activate.bat $ pip install flask SQLAlchemy flask-sqlalchemy そうした上で、app.pyを以下のように作成 import enum from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) class SexType(enum.Enum):   men = 'men'   women = 'women'   other = 'other' class User(db.Model):   id = db.Column(db.Integer, primary_key=True)   username = db.Column(db.String(80), unique=True, nullable=False)   sex = db.Column(db.Enum(SexType))   def __repr__(self):     return '<User %r Sex %r>' % (self.username, self.sex) 続けてテーブル作成・データ登録・確認を以下のように... $ python >>> from app import db,User,SexType >>> db.create_all() >>> hoge=User(username='ほげほげ', sex=SexType.men) >>> db.session.add(hoge) >>> db.session.commit() >>> User.query.all() [<User 'ほげほげ' Sex <SexType.men: 'men'>>] >>> quit() $ sqlite3 /tmp/test.db sqlite> select * from User; 1|ほげほげ|men sqlite> .q $ で、改めて、この後どうしたときどうなったので、何が問題だと言ってるのでしょうか?
退会済みユーザー

退会済みユーザー

2021/06/04 23:49

※先頭空白が使えないので、半角空白2個を全角1個に置換して書き込みしています。
baboo

2021/06/05 03:15

ご指摘ありがとうございます!おっしゃる通りです、以降何度も聞かれずに良いように質問いたします! そしてそのような質問でも懇切丁寧にご対応いただきありがとうございます! こちらsqliteにて再度試したところ、当初発生していた事象は発生しませんでした。。。 当初困っていたこととしては、SexTypeの変数名と値を class SexType(enum.Enum):   man = 'man'   woman = 'woman'   other = 'other' に変更(menをman、womenをwomanに変更)し、 >>> from app import db,User,SexType >>> db.create_all() >>> hoge=User(username='ほげほげ', sex='man') >>> db.session.add(hoge) >>> db.session.commit() とすると sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input value for enum sextype: "man" というエラーが出たため、一度テーブルを作り直そうと思い、 $ python >>> from app import db >>> db.drop_all() とすると sqlalchemy.exc.InternalError: (psycopg2.errors.DependentObjectsStillExist) cannot drop type sextype because other objects depend on it DETAIL: column sex of table "user" depends on type sextype とエラーが出たので、 $ psql dev_lsbdb [dev_lsbdb=# DROP TABLE users; とPostgreSQLの方に直接ログインし、テーブルを削除した上で、 $ python >>> from app import db,User >>> db.create_all() >>> hoge=User(username='ほげほげ', sex='man') >>> db.session.add(hoge) >>> db.session.commit() とすると sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input value for enum sextype: "man" とmenからmanへの変更が上書きされていない?ような挙動となり、コミットができないといった状況でした。 なおclass SexTypeのクラス名自体をclass Sexなどに変更するとテーブル削除&再作成後にsex = 'man'でのコミットが可能となりました。 sqliteの場合は特にテーブルの削除自体が必要なく、sexのカラムにmenとmanが共存しているような状況になっています。 かなりややこしくなってきてしまったので、もし思い当たることがあれば、くらいのご回答で大丈夫です。。。すみません!
退会済みユーザー

退会済みユーザー

2021/06/05 05:21

再現手順が欲しかったのですが…多分こういうことですね? docker-compose.ymlを以下のように用意 version: "3" services:  db:   image: postgres   ports:    - "5432:5432"   environment:    - POSTGRES_USER=postgres    - POSTGRES_DB=postgres    - POSTGRES_PASSWORD=secret   volumes:    - ./data:/var/lib/postgresql/data テーブル名がシステムテーブルと被るしデータベース作成 $ docker-compose up -d $ docker-compose exec db bash root@cb75de536075:/# psql -U postgres postgres=# create database hoge postgres=# exit root@cb75de536075:/# exit $ app.pyをpostgres用に改修するため、まずドライバインストール(今回はpure pythonが良かったのでpg8000) $ pip install pg8000 コピーして $ cp app.py app_postgres.py こんな差分になるように改修 $ diff app* 6c6 < app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' --- > app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+pg8000://postgres:secret@localhost:5432/hoge' $ スキーマ作成他データ作成コミットまで。 >>> from app_postgres import db,User,SexType >>> db.create_all() >>> ...(以降の手順は同じ) DB上で確認 $ docker-compose exec db bash # psql -d hoge -U postgres hoge=# \d public.user Table "public.user" Column | Type | Collation | Nullable | Default ----------+-----------------------+-----------+----------+---------------------------------- id | integer | | not null | nextval('user_id_seq'::regclass) username | character varying(80) | | not null | sex | sextype | | | Indexes: "user_pkey" PRIMARY KEY, btree (id) "user_username_key" UNIQUE CONSTRAINT, btree (username) hoge=# \dT+ sextype List of data types Schema | Name | Internal name | Size | Elements | Owner | Access privileges | Description --------+---------+---------------+------+----------+----------+-------------------+------------- public | sextype | sextype | 4 | men +| postgres | | | | | | women +| | | | | | | other | | | (1 row) hoge=# というわけで、postgresqlではenumがユーザー定義型としてマッピングされるようです。 DDLの変更が必要です。 結局質問が有耶無耶にもなっていて、回答もできませんが、本来ORMを使用しDDLの変更を伴うような変更が必要な場合、通常はマイグレーションを行います。 https://qiita.com/c0ridrew/items/68bba2c9f400345f7cf3 enumをどうマップするかは結構グレーな部分なので、よくよく検討して使う必要がそもそもあると思います。結局私もこれ以上時間を使いたくないので、この辺で。 今回は質問もコメントも内容が不十分だったので、次回は、ちゃんと質問、コメントしてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問