2013-04-16 15 views
11

Mam do czynienia z relacji wiele do wielu z sqlalchemy. Moje pytanie brzmi: jak uniknąć dodawania zduplikowanych wartości par w tabeli relacyjnej wiele do wielu.Jak uniknąć dodawania duplikatów w tabeli relacji wielu do wielu w SQLAlchemy - python?

Aby wszystko było bardziej zrozumiałe, wykorzystam przykład z oficjalnej dokumentacji 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() 

Z tego kodu, dane wstawione w tabelach jest następująca:

Rodzice tabeli:

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

Dzieci tabeli:

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

Parents2children stół

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

Jak widać, istnieje duplikat w ostatnim stole ... w jaki sposób mogę zapobiec SQLAlchemy z dodaniem tych duplikatów?

Próbowałem umieścić relacji ("dziecko", wtórny = ... collection_class = ustawiony) ale wyświetla się ten błąd:

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

nie można sprawdzić, czy związek istnieje, przed dodaniem go ponownie? – user1451340

Odpowiedz

6

Dodaj PrimaryKeyConstraint (lub UniqueKeyConstraint) do relationship tabeli:

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

i kod wygeneruje błąd przy próbie zatwierdzić relację dodaną z obu stron. Jest to bardzo zalecane.

W celu jeszcze nie wygeneruje błąd, tylko najpierw sprawdzić:

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

który prawie działa :) ale jak mogę zapobiec SQL Alchemy z dodawania takich samych wpisów w tabeli "dzieci" na przykład? –

Powiązane problemy