Oldukça eski bir gönderi, ancak bunun için bir veya iki saat geçirdim, bu yüzden bulduğumu paylaşmak istedim, özellikle de listelenen diğer yorumlardan bazıları pek doğru olmadığı için.
TL; DR
Alt tabloya bir yabancı verin veya mevcut olanı değiştirerek ondelete='CASCADE'
şunları ekleyin :
parent_id = db.Column(db.Integer, db.ForeignKey('parent.id', ondelete='CASCADE'))
Ve biri şu ilişkilerinin:
a) Bu üst tablodaki:
children = db.relationship('Child', backref='parent', passive_deletes=True)
b) Veya alt masada şu:
parent = db.relationship('Parent', backref=backref('children', passive_deletes=True))
ayrıntılar
Öncelikle, kabul edilen cevabın söylediğine rağmen, ebeveyn / çocuk ilişkisi kullanılarak relationship
kurulmaz, kullanılarak kurulur ForeignKey
. relationship
Üst veya alt masalara koyabilirsiniz ve iyi çalışacaktır. Görünüşe göre, alt masalarda,backref
anahtar kelime bağımsız değişkenine ek olarak işlevi de .
1. Seçenek (tercih edilir)
İkincisi, SqlAlchemy iki farklı basamaklandırmayı destekler. İlki ve önerdiğim, veritabanınızda yerleşiktir ve genellikle yabancı anahtar bildiriminde bir kısıtlama biçimini alır. PostgreSQL'de şöyle görünür:
CONSTRAINT child_parent_id_fkey FOREIGN KEY (parent_id)
REFERENCES parent_table(id) MATCH SIMPLE
ON DELETE CASCADE
Bu, içinden bir kaydı sildiğinizde parent_table
, içindeki tüm ilgili satırların child_table
veritabanı tarafından sizin için silineceği anlamına gelir . Hızlı ve güvenilirdir ve muhtemelen en iyi seçeneğinizdir. Bunu SqlAlchemy'de şu şekilde ayarlıyorsunuz ForeignKey
(alt tablo tanımının bir parçası):
parent_id = db.Column(db.Integer, db.ForeignKey('parent.id', ondelete='CASCADE'))
parent = db.relationship('Parent', backref=backref('children', passive_deletes=True))
ondelete='CASCADE'
Yaratan parçasıdır ON DELETE CASCADE
masaya.
Anladım!
Burada önemli bir uyarı var. Bir relationship
ile nasıl belirtildiğime dikkat edin passive_deletes=True
? Buna sahip değilseniz, her şey işe yaramayacak. Bunun nedeni, bir ana kaydı sildiğinizde SqlAlchemy'nin varsayılan olarak gerçekten tuhaf bir şey yapmasıdır. Tüm alt satırların yabancı anahtarlarını olarak ayarlar NULL
. Eğer bir satırı silerseniz parent_table
nerede id
= 5, o zaman temelde çalıştırır
UPDATE child_table SET parent_id = NULL WHERE parent_id = 5
Neden bunu istiyorsun, hiçbir fikrim yok. Birçok veritabanı motoru NULL
, bir yetim oluşturarak geçerli bir yabancı anahtar belirlemenize izin verse bile şaşırırdım. Kötü bir fikir gibi görünüyor, ama belki bir kullanım durumu vardır. Her neyse, SqlAlchemy'nin bunu yapmasına izin verirseniz, veritabanının kurduğunuz programı kullanarak çocukları temizlemesini engellersiniz ON DELETE CASCADE
. Bunun nedeni, hangi alt satırların silineceğini bilmek için bu yabancı anahtarlara güvenmesidir. SqlAlchemy hepsini olarak ayarladıktan NULL
sonra veritabanı bunları silemez. Ayarlamak passive_deletes=True
SqlAlchemy'nin NULL
yabancı anahtarları dışarı çıkarmasını engeller .
SqlAlchemy belgelerinde pasif silmeler hakkında daha fazla bilgi edinebilirsiniz .
seçenek 2
Bunu yapmanın diğer yolu, SqlAlchemy'nin sizin için yapmasına izin vermektir. Bu kullanılarak kurulur cascade
ve argüman relationship
. İlişki ana tabloda tanımlanmışsa, şöyle görünür:
children = relationship('Child', cascade='all,delete', backref='parent')
İlişki çocuk üzerindeyse, bunu şöyle yaparsın:
parent = relationship('Parent', backref=backref('children', cascade='all,delete'))
Yine, bu çocuk, bu yüzden adlı bir yöntemi çağırmalısınız backref
ve basamaklı verileri oraya koymalısınız.
Bunun yerine, bir üst satırı sildiğinizde, SqlAlchemy aslında alt satırları temizlemeniz için silme ifadelerini çalıştıracaktır. Bu, muhtemelen bu veritabanının sizin için işlemesine izin vermek kadar verimli olmayacaktır, bu yüzden bunu önermiyorum.
Desteklediği basamaklı özelliklerle ilgili SqlAlchemy belgeleri .