Way*_*ner 6 python postgresql sqlalchemy
我有一个遗留数据库,它使用各种存储过程为多个列创建默认值.尝试追踪名称并向我的代码添加查询会更加或更不容易,更不用说维护噩梦了.
我会想是能够告诉SQLAlchemy的忽略,我真的不关心列.不幸的是,事实并非如此.相反,它提供null违反数据库约束的值.
这是我的意思的一个例子:
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://user@host: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)
Run Code Online (Sandbox Code Playgroud)
这个barfs,因为:
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).
Run Code Online (Sandbox Code Playgroud)
我所期望的是它会跳过fnord列,因为它没有设置.
即使我这样做:
w = Whatever()
w.value = 'this breaks too'
Run Code Online (Sandbox Code Playgroud)
或添加:
def __init__(self, value):
self.value = value
Run Code Online (Sandbox Code Playgroud)
在Whatever类......仍然没有骰子.
我怎么能告诉sqlalchemy"看,这些其他专栏都没问题,我知道我没有提供价值 - 数据库会为我照顾它.没关系,只是不要担心这些专栏"?
我知道的唯一方法是使用类的定义和骗futz,说那些列不存在...但我也确实希望他们进来的查询.
添加服务器端默认使用server_default的fnord:
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)
Run Code Online (Sandbox Code Playgroud)
SQLAlchemy 很高兴地让默认的服务器端做它的事情,如果只是告诉它的话。如果您的列在 DDL 中没有设置默认值,而是通过触发器、存储过程等,请查看FetchedValue.
使用 SQLite 进行测试:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1490 次 |
| 最近记录: |