質問は実際にSQLAlchemy宣言型モデルを更新してバリデーターを実行する方法です。私の場合、User.name = name
のようなセッターを使用することは、実際にはオプションではありません。以下はバリデータを実行中に辞書データを使用して宣言型SQLAlchemyモデルを更新する方法
は、あなただけのインスタンスの属性を設定するsetattr()
を使用してではなく、単純な更新方法を提供し、あなたのモデルへのミックスインを追加することができ、私は
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import validates
from sqlalchemy.ext.declarative import declarative_base
some_engine = create_engine('sqlite://')
Session = sessionmaker(bind=some_engine)
session = Session()
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
@validates('name')
def validate_name(self, key, value):
if value != 'asd':
raise ValueError('not asd')
return value
Base.metadata.create_all(bind=some_engine)
user = User(id=1, name='qwe')
# >>> ValueError: not asd
user = User(id=1, name='asd')
session.add(user)
session.commit()
session.query(User).filter(User.id=1).update({'name': 'qwe'})
session.query(User).filter(User.id==1)[0].name
# >>> 'qwe'
上のループを使用しますvalidates decoratorは[AttributeEvents](http://docs.sqlalchemy.org/)の上にある便利な機能ですja/latest/orm/events.html#sqlalchemy.orm.events.AttributeEvents)。そのため、一括更新では機能しません。更新前などのMapperイベントは一括更新でも起動しません。 "Query.update()メソッドは"一括操作 "であり、ORM作業単位自動化をバイパスしてパフォーマンスを向上させました。**すべての警告をお読みくださいそして以下の警告。あなたは "not asd"を強制するためにDBレベルでCHECK制約を追加することができます。 –
SQLAlchemyでのCHECK制約の定義:http://docs.sqlalchemy.org/en/latest/core/constraints.html#check-constraint –
「作業単位自動化をバイパスする」という免責事項は何も教えてくれません残念ながら、SQLAlchemyのドキュメントは本当に面倒で厄介です:( – user541905