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

2020-05-28 22:44:29 +08:00
 LennonChin
试了很多种方法都不行,一对多倒是可以用无外键的方式写。

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

基本现在能找到的写法都会在关联表里产生外键。
LennonChin
2020-06-02 19:26:10 +08:00
@neoblackcap 你好,可以给个简单的示例吗?我试了一些方式都不成功。
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
2020-06-03 12:06:27 +08:00
@CRITICAL7 这种写法我写过,但稍微有点小问题,你在反序列化的时候,user 对象会有一个 address 字段,而每个 address 字段实际上是 UserAddress 对象,你再对 user 对象序列化,address 的格式大概是这样,address:[1,2,3],但数组中的数字是 UserAddress 的主键,不是 address 表的主键
johnsona
2020-06-03 12:07:49 +08:00
多对多实际上是你查询 user,带出来的 address 字段应该是 Address 对象,这时候三表连接好啦,你可以看看 lazy 属性,或许有收获,不过带来的性能损耗你是不想承受的
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
2020-06-04 09:45:18 +08:00
use_list=True 一对多,False 一对一,layz="dynamic"就相当于,需要得时候再查,还可以接着过滤,backref 同理
gjquoiai
2020-06-05 10:51:36 +08:00
@jsisjs20130824 emm 这就是小问题了。。用 proxy 啥的都能解决
johnsona
2020-06-05 15:50:14 +08:00
@yuchenyang1994 人家问的是多对多,你的这个我已经贴 gist 了
johnsona
2020-06-05 15:51:11 +08:00
@gjquoiai proxy 解决啥,你要分库分表啦
SjwNo1
2020-06-05 18:41:28 +08:00
额外建一个 bridge 表可行吗
gjquoiai
2020-06-05 18:55:33 +08:00
@jsisjs20130824 sqlalchemy association proxy

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/676479

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX