Elixir (SqlAlchemy):三张带复合主键的表之间的关系
我有三个表:
- 一个公司表,主键是
(company_id)
- 一个页面表,主键是
(company_id, url)
,并且有一个外键指向公司表 - 一个属性表,主键是
(company_id, attr_key)
,也有一个外键指向公司表。
我的问题是,如何利用属性表中的现有列(也就是 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))
我已经注释掉了一些失败的尝试。
最终,属性表中的 company_id
需要同时作为页面表和公司表的外键(同时也是属性表的主键)。
这可能吗?
1 个回答
2
是的,你可以这样做。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))