2016-08-31 12 views
4

さまざまなストアドプロシージャを使用していくつかの列のデフォルト値を作成するレガシーデータベースがあります。メンテナンスの悪夢はもちろんのこと、名前を追跡したり、コードにクエリを追加することは、多かれ少なかれ禁止されています。sqlalchemyにINSERTの特定の(ヌル)列を無視するように指示するには

私はのようにのように、私が本当に気にしない列を無視するようにsqlalchemyに指示することができます。残念ながら、それはしません。代わりに、nullの値はDB制約に違反しています。ここで

は、私が何を意味するかの例です:

import sqlalchemy as sa 
import logging 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 

l = logging.getLogger('sqlalchemy.engine') 
l.setLevel(logging.INFO) 
l.addHandler(logging.StreamHandler()) 




engine = sa.create_engine('postgresql+psycopg2://[email protected]:port/dbname') 

Session = sessionmaker(bind=engine) 
session = Session() 
temp_metadata = sa.MetaData(schema='pg_temp') 
TempBase = declarative_base(metadata=temp_metadata) 

with session.begin(subtransactions=True): 
    session.execute(''' 
     CREATE TABLE pg_temp.whatevs (
      id  serial 
      , fnord text not null default 'fnord' 
      , value text not null 
     ); 

     INSERT INTO pg_temp.whatevs (value) VALUES ('something cool'); 
    ''') 

    class Whatever(TempBase): 
     __tablename__ = 'whatevs' 

     id = sa.Column('id', sa.Integer, primary_key=True, autoincrement=True) 
     fnord = sa.Column('fnord', sa.String) 
     value = sa.Column('value', sa.String) 

    w = Whatever(value='something cool') 
    session.add(w) 

これはbarfs、ので:私はを期待することは、それはそれ以来、fnordカラム上でスキップするだろうということです

INSERT INTO pg_temp.whatevs (fnord, value) VALUES (%(fnord)s, %(value)s) RETURNING pg_temp.whatevs.id 
{'fnord': None, 'value': 'something cool'} 
ROLLBACK 
Traceback (most recent call last): 
    File "/home/wayne/.virtualenvs/myenv/lib64/python3.5/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context 
    context) 
    File "/home/wayne/.virtualenvs/myenv/lib64/python3.5/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute 
    cursor.execute(statement, parameters) 
psycopg2.IntegrityError: null value in column "fnord" violates not-null constraint 
DETAIL: Failing row contains (2, null, something cool). 

設定されていませんでした。私がやる場合でも

w = Whatever() 
w.value = 'this breaks too' 

または追加します。

def __init__(self, value): 
    self.value = value 

Whateverクラスに...まだサイコロ。

どのようにsqlalchemyに「見て、これらの他の列は大丈夫ですか、私は値を提供していないことを知っています - データベースはそれを世話します。これらの列 "?

私が知っている唯一の方法は、クラス定義とfutzして、それらの列は存在しないと言っているが... doは実際にクエリに来ることを望んでいる。

答えて

2

fnordためserver_defaultserver side defaultを追加します。ちょうどそれについて語っ場合

class Whatever(TempBase): 
    __tablename__ = 'whatevs' 

    id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) 
    fnord = sa.Column(sa.String, nullable=False, server_default='fnord') 
    value = sa.Column(sa.String, nullable=False) 

SQLAlchemyのは非常に喜んでデフォルトをすることができますが、その事のサーバー側を行います。 DDLにデフォルトセットがなく、through triggers、ストアドプロシージャなどの列がある場合は、FetchedValueを参照してください。 SQLiteのと

テスト: `FetchedValue`は、私が必要な正確に何のおかげであるよう

In [8]: engine.execute("""CREATE TABLE whatevs (
    ...: id INTEGER NOT NULL, 
    ...: fnord VARCHAR DEFAULT 'fnord' NOT NULL, 
    ...: value VARCHAR NOT NULL, 
    ...: PRIMARY KEY (id) 
    ...:)""") 

In [12]: class Whatever(Base): 
    ...:  __tablename__ = 'whatevs' 
    ...:  id = Column(Integer, primary_key=True, autoincrement=True) 
    ...:  fnord = Column(String, nullable=False, server_default="fnord") 
    ...:  value = Column(String, nullable=False) 
    ...:  

In [13]: session.add(Whatever(value='asdf')) 

In [14]: session.commit() 
2016-08-31 23:46:09,826 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 
INFO:sqlalchemy.engine.base.Engine:BEGIN (implicit) 
2016-08-31 23:46:09,827 INFO sqlalchemy.engine.base.Engine INSERT INTO whatevs (value) VALUES (?) 
INFO:sqlalchemy.engine.base.Engine:INSERT INTO whatevs (value) VALUES (?) 
2016-08-31 23:46:09,827 INFO sqlalchemy.engine.base.Engine ('asdf',) 
INFO:sqlalchemy.engine.base.Engine:('asdf',) 
2016-08-31 23:46:09,828 INFO sqlalchemy.engine.base.Engine COMMIT 
INFO:sqlalchemy.engine.base.Engine:COMMIT 
+0

に見えます! –

関連する問題