2014-04-27 1 views
9

Ich habe folgendes SQLAlchemy Setup:SQLAlchemy: direkt Objekt löschen von einer Eins-zu-viele-Beziehung ohne session.delete() verwendet

Base = declarative_base() 

class Post(Base): 
    __tablename__ = 'post' 
    id = Column(Integer, primary_key=True) 
    title = Column(String(30)) 
    comments = relationship('Comment', cascade='all') 

class Comment(Base): 
    __tablename__ = 'comment' 
    id = Column(Integer, primary_key=True) 
    post_id = Column(Integer, ForeignKey(Post.id, ondelete='CASCADE'), nullable=False) 
    text = Column(Text) 

Damit ich Post Objekte mit einer Eins-erstellen viele Beziehung zu Kommentaren. Ich möchte die Erstellung und das Löschen von Kommentaren für Posts verwalten, ohne auf die Sitzung Bezug zu nehmen. Hinzufügen um einen Kommentar zu einem Post funktioniert gut:

post = Post(title='some post') 
comment = Comment(text='some comment') 
post.comments.append(comment) 

Meine Session-Handler nur über Beiträge kennen, so wäre es ein session.add(post) tun und der Kommentar in die Sitzung automatisch platziert und mit der Datenbank auf den nächsten session.commit() syncronized . Das Gleiche gilt jedoch nicht für das Löschen von Kommentaren. Ich möchte einen Kommentar löschen können, indem Sie gerade tun:

post.comments.remove(comment) 

Doch dies erzeugt den folgenden Fehler auf der nächsten session.commit():

sqlalchemy.exc.OperationalError: (OperationalError) (1048, "Column 'post_id' cannot be null") 'UPDATE comment SET post_id=%s WHERE comment.id = %s' (None, 1L) 

Wie kann ich feststellen SQLAlchemy nicht den Kommentar aktualisieren mit ein Wert für post_id (was wegen der Nicht-Null-Einschränkung für die Spalte nicht erlaubt ist), aber löschen Sie stattdessen den Kommentar? Ich weiß, dass ich session.delete(comment) tun konnte, aber da ich den Kommentar der Sitzung nicht explizit hinzufügen musste, sehe ich keinen Grund, warum ich ihn explizit aus der Sitzung löschen müsste.

Ich habe mehrere Lösungen gefunden, um gelöschte Objekte zu verwandten Objekten zu kaskadieren, aber da ich niemals explizite Löschungen an der Sitzung mache (der Beitrag ist immer noch da), glaube ich nicht, dass das anwendbar ist.

Bearbeiten: Ich habe das Beispiel angepasst, um die Kaskadierung von Löschungen aus den Beiträgen zu enthalten. Jetzt funktioniert es zu tun session.delete(post) und alle Kommentare werden gelöscht. Aber ich möchte nur die Kommentare löschen, die ich aus der Beziehung entfernt habe, und nicht den gesamten Beitrag mit allen Kommentaren löschen.

TL; DR: Wie sage ich SQLAlchemy, eine Löschanweisung anstelle einer Aktualisierungsanweisung auszugeben, wenn ich einen Eintrag aus einer Beziehungsliste einer Eins-zu-viele-Beziehung entferne?

Antwort

5

lesen Configuring delete/delete-orphan Cascade Abschnitt der Dokumentation für weitere Informationen, aber im Grunde müssen Sie delete-orphan auch in Ihrer cascade Option des relationship:

class Post(Base): 
    # ... 
    comments = relationship('Comment', cascade="all, delete-orphan") 
+0

Mit der Option "delete-orphan" in den Kaskaden funktioniert das Löschen nach dem Entfernen aus der Beziehungsliste wie erwartet. Vielen Dank. – Varicus

0

Ich bin kein SQLAlchemy Benutzer, aber ich denke, Sie die onDelete Option

 
    post_id = Column(Integer, ForeignKey(Post.id, ondelete="CASCADE"), nullable=False) 

See, Mysql 5.6 Handbuch 13.6.44, Fremdschlüssel-Beschränkungen

 
SET NULL: Delete or update the row from the parent table, and set the foreign key column or columns in the child table to NULL. 
Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported. 
 
CASCADE: Delete or update the row from the parent table, and automatically delete or update the matching rows in the child table. 
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between two tables, do not define several ON UPDATE 
CASCADE clauses that act on the same column in the parent table or in the child table. 

Und verwenden sollten http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html Abschnitt: Fremdschlüssel definieren -> ON UPDATE und ON DELETE

+0

die wahrscheinlich funktionieren würde, wenn die Post Löschen mit 'session.delete (post)', aber Ich mache das nicht. Es gibt also nichts, was auf den Kommentar herunterfällt. Ich möchte nur den Kommentar löschen. – Varicus

Verwandte Themen