简体   繁体   English

SQLAlchemy多对多,无需外键

[英]SQLAlchemy many-to-many without foreign key

Could some one help me figure out how should i write primaryjoin/secondaryjoin on secondary table that lacking one ForeignKey definition. 有人可以帮我弄清楚我应该如何在缺少一个ForeignKey定义的辅助表上编写primaryjoin / secondaryjoin。 I can't modify database itself since it's used by different application. 我不能修改数据库本身,因为它已被其他应用程序使用。

from sqlalchemy import schema, types, func, orm
from sqlalchemy.dialects.postgresql import ARRAY

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class A(Base):
    __tablename__ = 'atab'
    id = schema.Column(types.SmallInteger, primary_key=True)

class B(Base):
    __tablename__ = 'btab'
    id = schema.Column(types.SmallInteger, primary_key=True)

    a = orm.relationship(
        'A', secondary='abtab', backref=orm.backref('b')
    ) 

class AB(Base):
    __tablename__ = 'abtab'
    id = schema.Column(types.SmallInteger, primary_key=True)
    a_id = schema.Column(types.SmallInteger, schema.ForeignKey('atab.id'))
    b_id = schema.Column(types.SmallInteger)

I've tried specifing foreign on join condition: 我试过指定联接条件上的外国人:

a = orm.relationship(
    'A', secondary='abtab', backref=orm.backref('b'),
    primaryjoin=(id==orm.foreign(AB.b_id))
) 

But received following error: 但是收到以下错误:

ArgumentError: Could not locate any simple equality expressions involving locally mapped foreign key columns for primary join condition '"atab".id = "abtab"."a_id"' on relationship Category.projects.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or are annotated in the join condition with the foreign() annotation. To allow comparison operators other than '==', the relationship can be marked as viewonly=True.

You can add foreign_keys to your relationship configuration. 您可以将foreign_keys添加到您的关系配置中。 They mention this in a mailing list post : 他们在邮件列表中提到了这一点:

from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    logon = Column(String(10), primary_key=True)
    group_id = Column(Integer)

class Group(Base):
    __tablename__ = 'groups'
    group_id = Column(Integer, primary_key=True)
    users = relationship('User', backref='group',
        primaryjoin='User.group_id==Group.group_id',
        foreign_keys='User.group_id')

engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

u1 = User(logon='foo')
u2 = User(logon='bar')
g = Group()
g.users = [u1, u2]
session.add(g)
session.commit()
g = session.query(Group).first()
print([user.logon for user in g.users])

output: 输出:

['foo', 'bar']

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM