这已经在这里 几乎
得到了回答。在这里,这可以通过使用裸链接表进行 多对多
的优势而得到改善。 __
我在SQL和SqlAlchemy中都不擅长,但是由于我在较长时间内一直牢记此问题,因此我试图找到一种兼具以下优点的解决方案:具有附加属性的关联对象和诸如裸链接的
直接 关联表(它本身不提供关联对象)。通过 *** 作程序的其他建议,以下内容对我来说似乎很安静:
#!/usr/bin/env python3# coding: utf-8import sqlalchemy as sqAlfrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import sessionmaker, relationship, backreffrom sqlalchemy.ext.associationproxy import association_proxyengine = sqAl.create_engine('sqlite:///m2m-w-a2.sqlite') #, echo=True)metadata = sqAl.schema.metaData(bind=engine)base = declarative_base(metadata)class UserProfile(base): __tablename__ = 'user' id = sqAl.Column(sqAl.Integer, primary_key=True) full_name = sqAl.Column(sqAl.Unipre(80)) gender = sqAl.Column(sqAl.Enum('M','F','D', name='gender'), default='D', nullable=False) description = sqAl.Column(sqAl.Unipre(280)) following = association_proxy('followeds', 'followee') followed_by = association_proxy('followers', 'follower') def follow(self, user, **kwargs): Follow(follower=self, followee=user, **kwargs) def __repr__(self): return 'UserProfile({})'.format(self.full_name)class Follow(base): __tablename__ = 'follow' followee_id = sqAl.Column(sqAl.Integer, sqAl.ForeignKey('user.id'), primary_key=True) follower_id = sqAl.Column(sqAl.Integer, sqAl.ForeignKey('user.id'), primary_key=True) status = sqAl.Column(sqAl.Enum('A','B', name=u'status'), default=u'A') created = sqAl.Column(sqAl.DateTime, default=sqAl.func.now()) followee = relationship(UserProfile, foreign_keys=followee_id, backref='followers') follower = relationship(UserProfile, foreign_keys=follower_id, backref='followeds') def __init__(self, followee=None, follower=None, **kwargs): """necessary for creation by append()ing to the association proxy 'following'""" self.followee = followee self.follower = follower for kw,arg in kwargs.items(): setattr(self, kw, arg)base.metadata.create_all(engine, checkfirst=True)session = sessionmaker(bind=engine)()def create_sample_data(sess): import random usernames, fstates, genders = ['User {}'.format(n) for n in range(4)], ('A', 'B'), ('M','F','D') profs = [] for u in usernames: user = UserProfile(full_name=u, gender=random.choice(genders)) profs.append(user) sess.add(user) for u in [profs[0], profs[3]]: for fu in profs: if u != fu: u.follow(fu, status=random.choice(fstates)) profs[1].following.append(profs[3]) # doesn't work with followed_by sess.commit()# uncomment the next line and run script once to create some sample data# create_sample_data(session)profs = session.query(UserProfile).all()print( '{} follows {}: {}'.format(profs[0], profs[3], profs[3] in profs[0].following))print('{} is followed by {}: {}'.format(profs[0], profs[1], profs[1] in profs[0].followed_by))for p in profs: print("User: {0}, following: {1}".format( p.full_name, ", ".join([f.full_name for f in p.following]))) for f in p.followeds: print(" " * 25 + "{0} follow.status: '{1}'" .format(f.followee.full_name, f.status)) print(" followed_by: {1}".format( p.full_name, ", ".join([f.full_name for f in p.followed_by]))) for f in p.followers: print(" " * 25 + "{0} follow.status: '{1}'" .format(f.follower.full_name, f.status))
为关联对象定义两个关系似乎是必不可少的。该association_proxy方法似乎是不理想的自我指涉的关系调整。的的参数奥德
Follow构造似乎不符合逻辑的我,但只能这样(是这样解释这里)。
在第117页的Rick Copeland-Essential
Sqlalchemy一书中,您发现有关
secondary-parameter的以下注释
relationship():
请注意,如果使用SQLAlchemy的M:N关系功能,则联接表应 仅
用于将两个表联接在一起,而不用于存储辅助属性。如果需要使用中间联接表来存储关系的其他属性,则应改用两个1:N关系。
抱歉,这有点冗长,但是我喜欢可以直接复制,粘贴和执行的代码。这适用于Python 3.4和SqlAlchemy 0.9,但也可能适用于其他版本。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)