Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何创建默认值等于主键的sqlalchemy列?_Python_Postgresql_Sqlalchemy_Primary Key - Fatal编程技术网

Python 如何创建默认值等于主键的sqlalchemy列?

Python 如何创建默认值等于主键的sqlalchemy列?,python,postgresql,sqlalchemy,primary-key,Python,Postgresql,Sqlalchemy,Primary Key,我有一个类似这样的类: class Foo(Base): pk = Column(Integer, Sequence('foo'), primary_key=True) 我想创建另一个字段,ref,它默认等于新创建对象的pk。不幸的是,我使用的是Postgres,它有一个属性,所以我不能简单地将这两列都默认为Sequence对象 以下是我当前的解决方案: class Foo(Base): pk = Column(Integer, Sequence('foo'), primary

我有一个类似这样的类:

class Foo(Base):
    pk = Column(Integer, Sequence('foo'), primary_key=True)
我想创建另一个字段,
ref
,它默认等于新创建对象的
pk
。不幸的是,我使用的是Postgres,它有一个属性,所以我不能简单地将这两列都默认为Sequence对象

以下是我当前的解决方案:

class Foo(Base):
    pk = Column(Integer, Sequence('foo'), primary_key=True)
    ref = Column(Integer, index=True, nullable=False, default=func.currval('foo'))
然而,这取决于两件事:SQLAlchemy在
ref
之前生成带有
pk
的INSERT语句,以及Postgres从左到右求值表达式(因此
nextval()
pk
生成的调用总是发生在
currval
ref
生成的调用之前)

我将非常感谢任何关于如何做得更好的建议


编辑:还有一种更有效的解决方案,即设置
default=-1
或其他设置,并强制调用者更新
ref
字段。这对于SQLA/Postgres语义的更改更安全、更健壮,但对于类的客户端来说却非常不方便。

我建议使用触发器来设置该值。虽然我自己还没有测试过,但是可以在INSERT之后激活触发器,读取新行的PK值并用该值更新ref列。它似乎有点类似于,只是您希望触发器位于插入之后,而不是之前。

可以利用SQLAlchemy的ORM映射器事件:

from sqlalchemy import event

# Model from OP
class Foo(Base):
    pk = Column(Integer, Sequence('foo'), primary_key=True)
    ref = Column(Integer, index=True, nullable=False, default=-1)

    @staticmethod
    def fill_ref(mapper, connection, target):
        # Note: You cannot use ORM in the event callbacks
        connection.execute(mapper.mapped_table.update()
                                 .values(ref=target.pk))
                                 .where(table.c.pk==target.pk))

event.listen(Foo, 'after_insert', Foo.fill_ref)

这解决了什么问题?您正在创建“继承人”架构吗?我们正在引入对象的版本控制,需要保持与旧版本客户端应用程序的兼容性。我不确定我是否了解其中一个与另一个的关系。
Foo.ref
是否指向
Foo
中的另一个元组?连接意味着什么?它将如何被质疑?我很感激你在这里急于解决更大的问题,但它涉及到相当多的背景来解释,我们已经在探索一系列不同的选择。我真的很想知道是否有办法让SQLAlchemy下一次引用同一序列两次。酷,我试过了,它成功了。但有一个问题——我怎么可以访问这里的
pk
属性?我习惯于在提交后才出现,但我想我的sqlalchemy模型在这里并不完整。@BenKuhn'after_insert'事件是在ORM在'insert'之后从DB接收对象之后发出的。这意味着已经调用了所有的db端处理和触发器。还有一个很重要的警告,就是不要使用修改会话的代码,因此您必须重新使用连接