目前有必要定义显式实体,如下所示:
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 支持属性提升的概念。这意味着在 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')