2013-04-16 8 views
11

私はsqlalchemyと多対多の関係を扱っています。私の質問は、多対多のリレーショナルテーブルに重複するペア値を追加しないようにする方法です。SQLAlchemyの多対多リレーションシップテーブル(Python)に重複を追加することを避けるにはどうすればいいですか?

もっと明確にするために、公式SQLAlchemyドキュメントの例を使用します。このコードで

Base = declarative_base() 

Parents2children = Table('parents2children', Base.metadata,                                                  
    Column('parents_id', Integer, ForeignKey('parents.id')),                                                  
    Column('children_id', Integer, ForeignKey('children.id')) 
) 

class Parent(Base): 
    __tablename__ = 'parents' 
    id = Column(Integer, primary_key=True) 
    parent_name = Column(String(45)) 
    child_rel = relationship("Child", secondary=Parents2children, backref= "parents_backref") 

    def __init__(self, parent_name=""): 
     self.parent_name=parent_name 
    def __repr__(self): 
     return "<parents(id:'%i', parent_name:'%s')>" % (self.id, self.parent_name) 

class Child(Base): 
    __tablename__ = 'children' 
    id = Column(Integer, primary_key=True) 
    child_name = Column(String(45)) 

    def __init__(self, child_name=""): 
     self.child_name= child_name 
    def __repr__(self): 
     return "<experiments(id:'%i', child_name:'%s')>" % (self.id, self.child_name) 

########################################### 

def setUp(): 
    global Session 
    engine=create_engine('mysql://root:[email protected]/db_name?charset=utf8', pool_recycle=3600,echo=False) 
    Session=sessionmaker(bind=engine) 

def add_data(): 
    session=Session() 
    name_father1=Parent(parent_name="Richard") 
    name_mother1=Parent(parent_name="Kate") 
    name_daughter1=Child(child_name="Helen") 
    name_son1=Child(child_name="John") 

    session.add(name_father1) 
    session.add(name_mother1) 

    name_father1.child_rel.append(name_son1) 
    name_daughter1.parents_backref.append(name_father1) 
    name_son1.parents_backref.append(name_father1) 

    session.commit() 
    session.close() 


setUp() 
add_data() 
session.close() 

、テーブルに挿入されたデータは以下の通りである:

親テーブル

+----+-------------+ 
| id | parent_name | 
+----+-------------+ 
| 1 | Richard  | 
| 2 | Kate  | 
+----+-------------+ 

子供テーブル

+----+------------+ 
| id | child_name | 
+----+------------+ 
| 1 | Helen  | 
| 2 | John  | 
+----+------------+ 

Parents2childrenテーブル

+------------+-------------+ 
| parents_id | children_id | 
+------------+-------------+ 
|   1 |   1 | 
|   1 |   2 | 
|   1 |   1 | 
+------------+-------------+ 

あなたが見ることができるように、最後のテーブルに重複があります...どのように私はSQLAlchemyのは、これらの重複を追加することを防ぐことができますか?

私は関係置くことを試みた( "子" を、二次= ...、collection_class =を設定する)が、このエラーが表示されます。

AttributeError: 'InstrumentedSet' object has no attribute 'append' 
+0

は、あなたは再びそれを追加する前に、関係がすでに存在するかどうかを確認できませんでしたか? – user1451340

答えて

6

は​​を追加(またはあなたのrelationshipテーブルにUniqueKeyConstraint):

Parents2children = Table('parents2children', Base.metadata,                                                  
    Column('parents_id', Integer, ForeignKey('parents.id')),                                                  
    Column('children_id', Integer, ForeignKey('children.id')), 
    PrimaryKeyConstraint('parents_id', 'children_id'), 
) 

、あなたがしようとすると、あなたのコードがエラーを生成します。両側から加えられた関係をコミットする。これは非常にお勧めします。

も、エラーを発生させないためには、単に最初のチェック:

if not(name_father1 in name_son1.parents_backref): 
    name_son1.parents_backref.append(name_father1) 
+1

はほとんど動作します:)しかし、どうすればSQL Alchemyが "子供"テーブルに同じエントリを追加するのを防ぐことができますか? –

関連する問題