I'm trying to allow users to 'favorite' different items in my web app. So, for example, a user can favorite a comment and favorite a news story. I then want to query all of the items a user has favorited, and load the assoc开发者_如何学JAVAiated objects (whether it be a news story or comment etc) polymorphically to display the list of objects to the user. I know how to create a one to one polymorphic relationship, however I have not been able to figure out many to many.
Thanks in advance
EDIT
In my one-to-one polymorphic relationship I have a one-many relation between users and user actions, and a one-one polymorphic relationship between user actions and the object the action was performed on. So in this case my user action table is like so:
class UserAction:  
  pass
user_actions = Table('user_action', metadata,  
    Column('id', Integer, autoincrement=True, primary_key=True),
    Column('module', String(30)),
    Column('created', DateTime, default=datetime.now),  
    Column('user_id', Integer, ForeignKey('user.id'))  
)
news table (one of the objects that can be accessed via a user action):
class News:  
  pass
news = Table('news', metadata,  
    Column('id', Integer, autoincrement=True, primary_key=True),  
    Column('title', String(30), nullable=False),  
    Column('action_id', Integer, ForeignKey('user_action.id'))  
)
And the mappers:
mapper(UserAction, user_actions, polymorphic_on=user_actions.c.module, polymorphic_identity='user_action')  
mapper(News, news, inherits=UserAction, polymorphic_identity='news')
As you can see, there is a clear one-one relation between a news object and the user_action record associated with it. This is because the user_action foreign key is in the news table. If I wanted to go about creating a a many to many polymorphic relation where multiple different object types can be favorited by many users how would I go about doing this? Thanks so much.
Your example defines one-to-many relation between UserAction and News. It looks like mess to me since I see no reason why News inherits from UserAction. To allow several user actions refering single news you have to define intermediate table with two foreign keys: one refering to UserAction and other to News. I see two reasonable ways to make it polymorphic:
- Use separate intermediate table for each favourited model class and define different relations in each UserActionsubclasses.
- Define separate foreign key for each favourited model in intermediate table and map it to class hierarchy with single-table inheritance (something like UserActionItem,UserActionNewsItemetc.).
But note, that all above is for linking UserAction and some entry models with many-to-many relation. While faouriting entries by users seems to me more like linking User with entry models.
Update: Below is working example. The only problem I see with it is that it allows duplicates.
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
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论