Эликсир (SqlAlchemy): отношения между 3 таблицами с составными первичными ключами - PullRequest
1 голос
/ 07 мая 2009

У меня есть 3 таблицы:

  • Таблица компании с (company_id) первичным ключом
  • Таблица страниц с (company_id, url) первичным ключом и внешним ключом обратно в компанию
  • Таблица Attr с (company_id, attr_key) первичным ключом и внешним ключом обратно в Company.

Мой вопрос заключается в том, как построить отношение ManyToOne из Attr обратно на страницу, используя существующие столбцы в Attr, т.е. company_id и url?

from elixir import Entity, has_field, setup_all, ManyToOne, OneToMany, Field, Unicode, using_options
from sqlalchemy.orm import relation

class Company(Entity):
    using_options(tablename='company')
    company_id = Field(Unicode(32), primary_key=True)
    has_field('display_name', Unicode(255))
    pages = OneToMany('Page')

class Page(Entity):
    using_options(tablename='page')
    company = ManyToOne('Company', colname='company_id', primary_key=True)
    url = Field(Unicode(255), primary_key=True)

class Attr(Entity):
    using_options(tablename='attr')
    company = ManyToOne('Company', colname='company_id', primary_key=True)
    attr_key = Field(Unicode(255), primary_key=True)
    url = Field(Unicode(255)) #, ForeignKey('page.url'))
    # page = ManyToOne('Page', colname=["company_id", "url"])
    # page = relation(Page, backref='attrs', foreign_keys=["company_id", "url"], primaryjoin=and_(url==Page.url_part, company_id==Page.company_id))

Я прокомментировал некоторые неудачные попытки.

В конце концов, Attr.company_id должен быть внешним ключом как для Page, так и для компании (а также первичным ключом в Attr).

Возможно ли это?

1 Ответ

2 голосов
/ 15 мая 2009

Да, вы можете сделать это. У Elixir нет встроенного способа сделать это, но поскольку это тонкая оболочка для SQLAlchemy, вы можете убедить его сделать это. Поскольку в Elixir отсутствует концепция отношения «многие к одному», в которой повторно используются существующие столбцы, вам необходимо использовать GenericProperty со свойством отношения SQLAlchemy и добавить внешний ключ с помощью параметров таблицы. Следующий код должен делать то, что вы хотите:

from elixir import Entity, has_field, setup_all, ManyToOne, OneToMany, Field, Unicode, using_options, using_table_options, GenericProperty
from sqlalchemy.orm import relation
from sqlalchemy import ForeignKeyConstraint

class Company(Entity):
    using_options(tablename='company')

    company_id = Field(Unicode(32), primary_key=True)
    display_name = Field(Unicode(255))
    pages = OneToMany('Page')

class Page(Entity):
    using_options(tablename='page')

    company = ManyToOne('Company', colname='company_id', primary_key=True)
    url = Field(Unicode(255), primary_key=True)
    attrs = OneToMany('Attr')

class Attr(Entity):
    using_options(tablename='attr')

    page = ManyToOne('Page', colname=['company_id', 'url'], primary_key=True)
    attr_key = Field(Unicode(255), primary_key=True)

    using_table_options(ForeignKeyConstraint(['company_id'], ['company.company_id']))
    company = GenericProperty(relation(Company))
...