V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
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 · 2017-10-06 21:24:57 +08:00 · 3326 次点击
    这是一个创建于 2640 天前的主题,其中的信息可能已经有所发展或是发生改变。

    官方文档

    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 条回复    2017-10-08 08:20:25 +08:00
    linnchord
        1
    linnchord  
       2017-10-06 23:11:42 +08:00
    可以啊,自己写程序实现关联呗。
    Tyanboot
        2
    Tyanboot  
       2017-10-07 01:20:03 +08:00
    当然可以啦, 比如说你有一个 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
       2017-10-07 18:34:27 +08:00
    @Tyanboot #2
    user = relationship("User", uselist=False, primaryjoin=foreign(user_id) == remote(User.id_))

    这不还是有 foreign 么
    Tyanboot
        4
    Tyanboot  
       2017-10-08 01:04:03 +08:00 via Android
    @cevincheung …首先你是不是被降权了,没收到通知

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

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

    no named module
    cevincheung
        6
    cevincheung  
    OP
       2017-10-08 08:20:25 +08:00
    @Tyanboot #4
    好吧,在 sqlalchemy.orm 中
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 20:45 · PVG 04:45 · LAX 12:45 · JFK 15:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.