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
LennonChin
V2EX  ›  Python

请问, SQLAlchemy 无外键约束的多对多关系模型该怎么写啊?

  •  
  •   LennonChin · 2020-05-28 22:44:29 +08:00 · 4447 次点击
    这是一个创建于 1638 天前的主题,其中的信息可能已经有所发展或是发生改变。
    试了很多种方法都不行,一对多倒是可以用无外键的方式写。

    Google 、Stack Overflow 都找过了,也没有找到正确的。
    21 条回复    2020-06-08 13:04:17 +08:00
    neoblackcap
        1
    neoblackcap  
       2020-05-28 23:51:02 +08:00
    多建一个多对多关系表,然后就好像普通情况一样用 join 声明关系
    qixiangyangrm
        2
    qixiangyangrm  
       2020-05-29 12:03:45 +08:00
    johnsona
        3
    johnsona  
       2020-05-29 13:36:11 +08:00
    +1,无外键写法也是 join 的
    johnsona
        4
    johnsona  
       2020-05-29 13:40:25 +08:00
    楼主搞定了吗,django 是软约束的,sqlalchemy 就一眼难尽了
    johnsona
        5
    johnsona  
       2020-05-29 13:41:04 +08:00
    可能这就是 flask 拥护者追求的可扩展吧,自由选择一个 orm,结果没几个 orm 可选
    johnsona
        6
    johnsona  
       2020-05-29 13:59:55 +08:00
    @qixiangyangrm 我试过,还是会生成外键
    johnsona
        7
    johnsona  
       2020-05-29 14:30:46 +08:00
    一对多,看着里,有效,实际上底层执行的 join
    https://gist.github.com/nickretallack/7cf6d4f255b248a9f6ec
    LennonChin
        8
    LennonChin  
    OP
       2020-06-02 19:24:51 +08:00
    @qixiangyangrm 这种写法第三张关联表里也有外键约束的
    LennonChin
        9
    LennonChin  
    OP
       2020-06-02 19:25:41 +08:00
    @jsisjs20130824 底层 Join 也可以,不过你贴的这个代码不是多对多吧,没有关联表

    基本现在能找到的写法都会在关联表里产生外键。
    LennonChin
        10
    LennonChin  
    OP
       2020-06-02 19:26:10 +08:00
    @neoblackcap 你好,可以给个简单的示例吗?我试了一些方式都不成功。
    CRITICAL7
        11
    CRITICAL7  
       2020-06-03 01:31:19 +08:00
    emm 就是这么写吧大概。。官网 tutorial 改了改

    ```
    class User(Base):
    id = Column(Integer, primary_key=True)


    class UserAddress(Base):
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer)
    address_id = Column(Integer)

    user = relationship("User", primaryjoin="foreign(UserAddress.user_id) == User.id")
    address = relationship("Address", primaryjoin="foreign(UserAddress.address_id) == Address.id")


    class Address(Base):
    id = Column(Integer, primary_key=True)
    ```
    johnsona
        12
    johnsona  
       2020-06-03 12:06:27 +08:00
    @CRITICAL7 这种写法我写过,但稍微有点小问题,你在反序列化的时候,user 对象会有一个 address 字段,而每个 address 字段实际上是 UserAddress 对象,你再对 user 对象序列化,address 的格式大概是这样,address:[1,2,3],但数组中的数字是 UserAddress 的主键,不是 address 表的主键
    johnsona
        13
    johnsona  
       2020-06-03 12:07:49 +08:00
    多对多实际上是你查询 user,带出来的 address 字段应该是 Address 对象,这时候三表连接好啦,你可以看看 lazy 属性,或许有收获,不过带来的性能损耗你是不想承受的
    yuchenyang1994
        14
    yuchenyang1994  
       2020-06-04 09:43:49 +08:00
    唉,看来还是得我来
    ```
    class User(Base):
    id = Column(Integer, primary_key=True)
    user = relationship("User", primaryjoin="foreign(User.id) == remote(UserAddress.id)", backref=backref("user"), use_list=False, lazy="dynamic")


    class UserAddress(Base):
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer)
    address_id = Column(Integer)

    ```
    yuchenyang1994
        15
    yuchenyang1994  
       2020-06-04 09:45:18 +08:00
    use_list=True 一对多,False 一对一,layz="dynamic"就相当于,需要得时候再查,还可以接着过滤,backref 同理
    gjquoiai
        16
    gjquoiai  
       2020-06-05 10:51:36 +08:00
    @jsisjs20130824 emm 这就是小问题了。。用 proxy 啥的都能解决
    johnsona
        17
    johnsona  
       2020-06-05 15:50:14 +08:00
    @yuchenyang1994 人家问的是多对多,你的这个我已经贴 gist 了
    johnsona
        18
    johnsona  
       2020-06-05 15:51:11 +08:00
    @gjquoiai proxy 解决啥,你要分库分表啦
    SjwNo1
        19
    SjwNo1  
       2020-06-05 18:41:28 +08:00
    额外建一个 bridge 表可行吗
    gjquoiai
        20
    gjquoiai  
       2020-06-05 18:55:33 +08:00
    @jsisjs20130824 sqlalchemy association proxy
    johnsona
        21
    johnsona  
       2020-06-08 13:04:17 +08:00
    @gjquoiai 然后使用 join 来代替 foreignkey 吗,这个就是用模型来生成中间表,感觉还可以,找机会试试
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2837 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 14:04 · PVG 22:04 · LAX 06:04 · JFK 09:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.