前提・実現したいこと
SQLAlcemyを利用したDBのinsert処理でDefault値にインスタンス変数を利用して設定したい
該当のソースコード
python
1from datetime import datetime 2from sqlalchemy import create_engine 3from sqlalchemy.orm import sessionmaker, scoped_session 4from sqlalchemy.ext.declarative import declarative_base 5from sqlalchemy import Column, Integer, String, Date, DateTime 6 7DB_FILE = "localdb.sqlite3" 8ENCODING = "utf-8" 9DB_ECHO = True 10 11# mysql 12# DATABASE = f"mysql://{USERNAME}:{PASSWORD}@{HOST}/{DBNAME}?charset={CHARSET}" 13 14# sqlite 15DATABASE = f"sqlite:///{DB_FILE}" 16 17ENGINE = create_engine( 18 DATABASE, 19 encoding=ENCODING, 20 echo=DB_ECHO 21) 22 23# session作成 24session = scoped_session( 25 sessionmaker( 26 autocommit=False, 27 autoflush=False, 28 bind=ENGINE 29 ) 30) 31 32DbBase = declarative_base() 33 34 35class Product(DbBase): 36 """ 37 商品モデル 38 """ 39 __tablename__ = 'products' 40 41 # 操作ユーザ 42 operation_user = "system" 43 44 # DBカラム定義 ############################################ 45 # key id 46 id = Column(Integer, primary_key=True) 47 # 製品ID 48 product_id = Column(String(50), nullable=False) 49 # タイトル 50 title = Column(String(200), nullable=False) 51 # 販売日 52 sales_date = Column(DateTime, nullable=False) 53 54 # 作成日 55 create_date = Column(DateTime, nullable=False, default=datetime.now) 56 # 作成者 57 create_user = Column(String(50), nullable=False, default=operation_user) 58 # 更新日 59 update_date = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now) 60 # 更新者 61 update_user = Column(String(50), nullable=False, default="operation_user", onupdate="operation_user") 62 63 64if __name__ == "__main__": 65 DbBase.metadata.drop_all(bind=ENGINE) 66 DbBase.metadata.create_all(bind=ENGINE) 67 68 items = list() 69 for i in range(0, 100): 70 product = Product() 71 product.product_id = "A" + f"{i:03}" 72 product.title = "ああああ" + f"{i:03}" 73 product.sales_date = datetime.now() 74 75 # 操作ユーザを指定したい 76 product.operation_user = "test" 77 items.append(product) 78 79 session.add_all(items) 80 session.commit()
発生している問題・エラーメッセージ・試したこと
① インスタンス変数をそのまま利用(上記ソース)
operation_user = "system" ・・ create_user = Column(String(50), nullable=False, default=operation_user)
とすると、初期値のsystem
となります
② initで初期化
operation_user = "system" ・・・ def __init__(self, user): self.operation_user = user ・・・ product = Product("test")
結果は変わりませんでした
ここまでは、Columnの定義時点の値が使われるんだろうなぁ、ぐらいで予想はしていたのですが。。。
③ 関数を介して参照
operation_user = "system" def get_operation_user(self): return self.operation_user ・・・ create_user = Column(String(50), nullable=False, default=get_operation_user)
下記エラーとなってしまいます
sqlalchemy.exc.StatementError: (builtins.AttributeError) 'SQLiteExecutionContext' object has no attribute 'operation_user' [SQL: INSERT INTO products (product_id, title, sales_date, create_date, create_user, update_date, update_user) VALUES (?, ?, ?, ?, ?, ?, ?)] [parameters: [{'product_id': 'A000', 'sales_date': datetime.datetime(2019, 12, 15, 21, 4, 6, 432239), 'title': 'ああああ000'}]]
④ システムカラムを作成して参照
operation_user = Column(String(20), system=True) def get_operation_user(context): return context.get_current_parameters()['operation_user'] ・・・ create_user = Column(String(50), nullable=False, default=get_operation_user)
これでいけそうかと思ったのですが、エラーが出てしまいます。
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table products has no column named operation_user [SQL: INSERT INTO products (operation_user, product_id, title, sales_date, create_date, create_user, update_date, update_user) VALUES (?, ?, ?, ?, ?, ?, ?, ?)] [parameters: ('test', 'A000', 'ああああ000', '2019-12-15 21:10:56.192422', '2019-12-15 21:10:56.202107', 'test', '2019-12-15 21:10:56.202107', 'operation_user')] (Background on this error at: http://sqlalche.me/e/e3q8)
Column
でsystem=True
としたことで、DDLには含まれなくしました。(テーブル定義を確認したところ作成はされていませんでした)
しかし、insertのSQLを確認すると、operation_user
カラムへinsert
しようとしてしまっています。
いろいろ試してみたのですが、どれもうまくいかなかったです。
よろしくお願いいたします。
補足情報(FW/ツールのバージョンなど)
sqlalchemy 1.3.11

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。