在 Pony ORM 中,可以“自动”创建多对多关系。例如,from the documentation (对于 0.6 版,强调我的):
In order to create many-to-many relationship you need to define both ends of the relationship as Set attributes:
class Product(db.Entity): tags = Set("Tag") class Tag(db.Entity): products = Set(Product)
In order to implement this relationship in the database, Pony will create an intermediate table. This is a well known solution which allows you to have many-to-many relationships in relational databases.
是否可以在自动创建的中间表中创建额外的属性(列),因此不仅是“产品”和“标签”的外键,还有时间戳?
如果是,如何?
如果没有,我想我将不得不显式创建中间表。在这种情况下,我还可以使用不错的
Set
- 属性定义(可能是中间表,表示感兴趣的属性)?
最佳答案
目前需要定义显式实体,如下所示:
class Product(db.Entity):
name = Required(str)
tags = Set("ProductTag")
class Tag(db.Entity):
name = Required(str, unique=True)
products = Set("ProductTag")
class ProductTag(db.Entity):
product = Required(Product)
tag = Required(Tag)
PrimaryKey(product, tag)
timestamp = Required(datetime, default=datetime.now)
Pony 不支持虚拟
Set
属性如 through
在 Django 中,但我们计划在 future 添加它们。现在您需要明确地使用中间表。为产品添加标签
p1 = Product[1]
tag1 = Tag.get(name='smartphones')
p1.tags.create(tag=tag1)
# or:
ProductTag(product=p1, tag=tag1)
从产品中删除标签:
ProductTag[p1, tag1].delete()
检查产品是否具有特定标签:
ProductTag.get(product=p1, tag=tag1) is not None
另外,Pony 支持 attribute lifting 的概念.这意味着在 Pony 中,任何集合属性都具有其项目的所有属性。此类集合属性的值是单个项目的所有值的集合。例如,为了获取特定产品的所有标签,您可以编写:
p1.tags.tag
p1.tags
表达式返回 ProductTag
的集合项目。每个ProductTag
对象有 tag
指向特定标签对象的属性。所以p1.tags.tag
返回所有 Tag
的集合与特定链接的对象 Product
目的。可以在查询中使用属性提升。例如,为了找到标签为
smartphones
的所有产品您可以编写以下查询:select(p for p in Product if 'smartphones' in p.tags.tag.name)
在这里,
p.tags
是 ProductTag
的集合对象,p.tags.tag
是Tag
的合集对象,以及 p.tags.tag.name
是标签名称的集合。上面的查询是以下查询的语法糖:select(p for p in Product if 'smartphones' in select(item.tag.name for item in p.tags))
此外,查询可以重写为:
select(pt.product for pt in ProductTag if pt.tag.name == 'smartphones')
关于attributes - 在 Pony ORM 中是否可以向多对多关系的中间表添加额外的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35411893/