Возможно ли в Pony ORM добавить дополнительные атрибуты в промежуточную таблицу отношения "многие ко многим"?

В Pony ORM возможно "автоматически" создать отношение "многие ко многим". Например, из документации (для версии 0.6, выделено мое):

Чтобы создать отношение "многие ко многим", необходимо определить оба конца отношения как "Задать атрибуты":

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

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

Чтобы реализовать эту связь в базе данных, Пони создаст промежуточную таблицу. Это хорошо известное решение, которое позволяет вам иметь отношения "многие ко многим" в реляционных базах данных.

Можно ли создать дополнительный атрибут (столбец) в автоматически создаваемой промежуточной таблице, чтобы не только внешние ключи для "Product" и "Tag", но, например, также временная метка?

Если да, то как?

Если нет, я думаю, мне придется явно создать промежуточную таблицу. Могу ли я в этом случае использовать хороший Setопределение атрибута (возможно, к промежуточной таблице с указанием атрибута интереса)?

1 ответ

Решение

В настоящее время необходимо определить явную сущность, например:

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)

Пони не поддерживает виртуальные 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')
Другие вопросы по тегам