您的示例定义了UserAction 和News 之间的一对多关系。这对我来说看起来很乱,因为我看不出News 继承自UserAction 的原因。要允许引用单个新闻的多个用户操作,您必须使用两个外键定义中间表:一个引用 UserAction,另一个引用 News。我看到了两种合理的方法来使它成为多态:
- 为每个喜欢的模型类使用单独的中间表,并在每个
UserAction 子类中定义不同的关系。
- 为中间表中的每个首选模型定义单独的外键,并将其映射到具有单表继承的类层次结构(例如
UserActionItem、UserActionNewsItem 等)。
但请注意,以上所有内容都是用于链接UserAction 和一些具有多对多关系的入门模型。虽然在我看来,用户添加条目更像是将 User 与条目模型链接。
更新:以下是工作示例。我看到的唯一问题是它允许重复。
from sqlalchemy import *
from sqlalchemy.orm import mapper, relation, sessionmaker
from sqlalchemy.ext.associationproxy import association_proxy
metadata = MetaData()
users = Table(
'users', metadata,
Column('id', Integer, nullable=False, primary_key=True),
)
news = Table(
'news', metadata,
Column('id', Integer, nullable=False, primary_key=True),
)
comments = Table(
'comments', metadata,
Column('id', Integer, nullable=False, primary_key=True),
)
favitems = Table(
'favitems', metadata,
Column('id', Integer, nullable=False, primary_key=True),
Column('user_id', Integer, ForeignKey(users.c.id), nullable=False),
Column('item_type', Integer, nullable=False),
Column('news_id', Integer, ForeignKey(news.c.id)),
Column('comment_id', Integer, ForeignKey(comments.c.id)),
)
class News(object): pass
class Comment(object): pass
class FavItem(object):
TYPE_NEWS = 1
TYPE_COMMENT = 2
def __new__(cls, item=None):
if isinstance(item, News):
cls = FavNews
elif isinstance(item, Comment):
cls = FavComment
return object.__new__(cls)
class FavNews(FavItem):
def __init__(self, item):
self.item_type = self.TYPE_NEWS
self.item = item
class FavComment(FavItem):
def __init__(self, item):
self.item_type = self.TYPE_COMMENT
self.item = item
class User(object):
favorites = association_proxy('_favitems', 'item', creator=FavItem)
mapper(News, news)
mapper(Comment, comments)
mapper(FavItem, favitems,
polymorphic_on=favitems.c.item_type)
mapper(FavNews, favitems,
inherits=FavItem,
polymorphic_identity=FavItem.TYPE_NEWS,
properties={
'item': relation(News),
})
mapper(FavComment, favitems,
inherits=FavItem,
polymorphic_identity=FavItem.TYPE_COMMENT,
properties={
'item': relation(Comment),
})
mapper(User, users,
properties={
'_favitems': relation(FavItem),
})
engine = create_engine('sqlite://')
metadata.create_all(engine)
session = sessionmaker(engine)()
user = User()
news1 = News()
news2 = News()
comment1 = Comment()
comment2 = Comment()
user.favorites = [news1, news2, comment1, comment2]
session.add(user)
session.commit()
user_id = user.id
session.expunge_all()
user = session.query(User).get(user_id)
print user.favorites