在Pony ORM中是否可以在多对多关系的中间表中添加额外的属性?

时间:2016-02-15 14:26:39

标签: attributes many-to-many ponyorm

在Pony ORM中,可以“自动”创建多对多关系。例如,from the documentation(对于版本0.6,强调我的):

  

为了创建多对多关系,您需要定义两者   设置属性的关系结束:

     
class Product(db.Entity):
    tags = Set("Tag")

class Tag(db.Entity):
    products = Set(Product)
     

为了在数据库中实现这种关系,Pony会   创建中间表。这是众所周知的解决方案   允许您在关系数据库中拥有多对多关系。

是否可以在自动创建的中间表中创建额外的属性(列),因此不仅仅是“产品”和“标记”的外键,还有例如时间戳?

如果是,怎么样?

如果没有,我想我必须明确地创建中间表。在这种情况下,我是否仍然可以使用漂亮的Set - 属性定义(可能是中间表,表示感兴趣的属性)?

1 个答案:

答案 0 :(得分:7)

目前有必要定义显式实体,如下所示:

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不支持Django中的Set等虚拟through属性,但我们计划将来添加它们。现在你需要明确地使用中间表。

向产品添加标记

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.tagsProductTag个对象的集合,p.tags.tagTag个对象的集合,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')