equ*_*ghe 4 attributes many-to-many ponyorm
在Pony ORM中,可以"自动"创建多对多关系.例如,从文档(对于版本0.6,强调我的):
要创建多对多关系,您需要将关系的两端定义为Set属性:
Run Code Online (Sandbox Code Playgroud)class Product(db.Entity): tags = Set("Tag") class Tag(db.Entity): products = Set(Product)为了在数据库中实现这种关系,Pony将创建一个中间表.这是一个众所周知的解决方案,它允许您在关系数据库中拥有多对多关系.
是否可以在自动创建的中间表中创建额外的属性(列),因此不仅仅是"产品"和"标签"的外键,还有例如时间戳?
如果有,怎么样?
如果没有,我想我必须明确地创建中间表.在这种情况下,我仍然可以使用nice Set-attribute定义(可能是中间表,指示感兴趣的属性)?
目前有必要定义显式实体,如下所示:
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)
Run Code Online (Sandbox Code Playgroud)
Pony不支持Django中的虚拟Set属性through,但我们计划在将来添加它们.现在你需要明确地使用中间表.
将标签添加到产品中
p1 = Product[1]
tag1 = Tag.get(name='smartphones')
p1.tags.create(tag=tag1)
# or:
ProductTag(product=p1, tag=tag1)
Run Code Online (Sandbox Code Playgroud)
从产品中删除标记:
ProductTag[p1, tag1].delete()
Run Code Online (Sandbox Code Playgroud)
检查产品是否具有特定标签:
ProductTag.get(product=p1, tag=tag1) is not None
Run Code Online (Sandbox Code Playgroud)
此外,Pony支持属性提升的概念.这意味着在Pony中,任何集合属性都具有其项目的所有属性.此类集合属性的值是各个项的所有值的集合.例如,为了获取特定产品的所有标签,您可以编写:
p1.tags.tag
Run Code Online (Sandbox Code Playgroud)
该p1.tags表达式返回的集合ProductTag项目.每个ProductTag对象都具有tag指向特定标记对象的属性.因此p1.tags.tag返回Tag与特定Product对象链接的所有对象的集合.
可以在查询中使用属性提升.例如,为了找到带有标记的所有产品,smartphones您可以编写以下查询:
select(p for p in Product if 'smartphones' in p.tags.tag.name)
Run Code Online (Sandbox Code Playgroud)
这里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))
Run Code Online (Sandbox Code Playgroud)
此外,查询可以重写为:
select(pt.product for pt in ProductTag if pt.tag.name == 'smartphones')
Run Code Online (Sandbox Code Playgroud)