【问题标题】:relationship with a sliced and casted value of the column in SQLAlchemy与 SQLAlchemy 中列的切片和强制转换值的关系
【发布时间】:2025-12-03 09:40:01
【问题描述】:

有什么方法可以分别基于parent_idid在Parent和Child之间创建这样的关系(示例数据):

家长
parent_id:“A1234”
name: "父名"

儿童
编号:1234

如何将外键添加到Childparent_idString。有没有办法将其切片然后转换为Integer


编辑: 另外,如果情况相反怎么办:

孩子:
child_id: "A1234"

家长:
父字母:“A”
parent_id: 1234

会不会是这样的:
primaryjoin=(child_id == (Parent.parent_letter + str(Parent.parent_id)))

remote_side 会是什么样子?还是整个relationship

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    请参阅文档的Creating Custom Foreign Conditions 部分。使用cast,可以为以下模型设置关系:

    class Parent(Base):
        __tablename__ = 'parent'
        parent_id = Column(String, primary_key=True)
        name = Column(String, nullable=False)
    
    
    class Child(Base):
        __tablename__ = 'child'
        id = Column(Integer, primary_key=True)
        name = Column(String, nullable=False)
    
        parent = relationship(
            Parent,
            primaryjoin=("A" + cast(id, String) == Parent.parent_id),
            foreign_keys=id,
            remote_side=Parent.parent_id,
            backref="children",
            # uselist=False,  # use in case of one-to-one relationship
        )
    

    在这种情况下,您可以查询 Parent.childrenChild.parent

    p1 = session.query(Parent).get('A1234')
    print(p1)
    print(p1.children)
    
    c1 = session.query(Child).get(1234)
    print(c1)
    print(c1.parent)
    

    但是您仍然无法创建如下关系项:

    p = Parent(
        parent_id='A3333', name='with a child',
        children=[Child(name='will not work')]
    )
    session.add(p)
    session.commit()  # this will fail
    

    Edit-1:对于您在 cmets 和编辑中提到的替代情况,以下关系定义应该有效(显然,模型的定义也不同):

    parent = relationship(
        Parent,
        primaryjoin=(
            foreign(child_id) ==
            remote(Parent.parent_letter + cast(Parent.parent_id, String))
        ),
        backref="children",
        uselist=False,
    )
    

    【讨论】:

    • 所以如果我想反过来做(child_id 是一个整数,parent_letter 是一个字符串,parent_id 是一个整数)我会做类似的事情:primaryjoin=(child_id == parent_letter + str(parent_id)) 吗?
    • 我猜是这样,但我不确定您在评论中提到的那些列是在哪些表上?
    • 子表上的 Child_id 和父表上的其余部分
    • 但是如果child_idparent_id都是Integers,那不是很简单ForeignKey吗?在这种情况下,parent_letter 的作用是什么?
    • 对不起,我没有正确解释。 Child_id 类似于“A1234”。 Parent_letter:“A” parent_id:1234
    最近更新 更多