V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
cevincheung
V2EX  ›  Python

SQLAlchemy 不使用 ForeignKey 如何进行关联?

  •  1
     
  •   cevincheung ·
    cevin · Oct 6, 2017 · 3705 views
    This topic created in 3125 days ago, the information mentioned may be changed or developed.

    官方文档

    class Address(Base):
         __tablename__ = 'addresses'
         id = Column(Integer, primary_key=True)
         email_address = Column(String, nullable=False)
         user_id = Column(Integer, ForeignKey('users.id'))
    
         user = relationship("User", back_populates="addresses")
    
         def __repr__(self):
             return "<Address(email_address='%s')>" % self.email_address
    

    这里 ForeignKey('users.id') 是必须的么? 可以不使用外键强制约束吗?

    6 replies    2017-10-08 08:20:25 +08:00
    linnchord
        1
    linnchord  
       Oct 6, 2017
    可以啊,自己写程序实现关联呗。
    Tyanboot
        2
    Tyanboot  
    PRO
       Oct 7, 2017
    当然可以啦, 比如说你有一个 users 表:

    class User(Base):
    __tablename__ = "users"
    id_ = Column(Integer, primary_key=True)
    name = Column(String(16))

    你还有一个 address 表:

    class Address(Base):
    __tablename__ = "address"
    id_ = Column(Integer, primary_key=True)
    place = Column(String(256))
    user_id = Column(Integer)

    user = relationship("User", uselist=False, primaryjoin=foreign(user_id) == remote(User.id_))

    你只需要在 relationship 里用 primaryjoin 来手动指定 join 关系就可以了, 前提是已经导入了 User. 这部分也在文档里提到了

    此外还可以写成

    relationship("User", uselist=False, foreign_keys=user_id, primaryjoin="Address.user_id==User.id_")

    这种写法同样要求已经导入 User, 但是会被 ide 识别为 unused import. 所以建议使用第一种
    cevincheung
        3
    cevincheung  
    OP
       Oct 7, 2017
    @Tyanboot #2
    user = relationship("User", uselist=False, primaryjoin=foreign(user_id) == remote(User.id_))

    这不还是有 foreign 么
    Tyanboot
        4
    Tyanboot  
    PRO
       Oct 8, 2017 via Android
    @cevincheung …首先你是不是被降权了,没收到通知

    其次虽然这里有 foreign,但实际上在数据库里面是不会有外键约束的。这里只是把这个 user_id 看作了外键,以便于进行 join 查询,和他本身是不是外键是没关系的。
    cevincheung
        5
    cevincheung  
    OP
       Oct 8, 2017
    @Tyanboot #4
    好像是吧……

    表示在 sqlalchemy 里并没有 foreign 和 remote 两个方法

    no named module
    cevincheung
        6
    cevincheung  
    OP
       Oct 8, 2017
    @Tyanboot #4
    好吧,在 sqlalchemy.orm 中
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   6078 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 02:06 · PVG 10:06 · LAX 19:06 · JFK 22:06
    ♥ Do have faith in what you're doing.