SQLAlchemy ORM - İlgili Nesneleri Silme
Tek bir tablo üzerinde silme işlemi yapmak kolaydır. Tek yapmanız gereken, eşlenen sınıfın bir nesnesini bir oturumdan silmek ve eylemi uygulamaktır. Ancak, birden çok ilişkili tablodaki silme işlemi biraz karmaşıktır.
Sales.db veritabanımızda Müşteri ve Fatura sınıfları, müşteri ve fatura tablosu ile bire birçok ilişki türü ile eşleştirilir. Müşteri nesnesini silmeye ve sonucu görmeye çalışacağız.
Hızlı bir referans olarak, Müşteri ve Fatura sınıflarının tanımları aşağıdadır -
from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
engine = create_engine('sqlite:///sales.db', echo = True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import relationship
class Customer(Base):
__tablename__ = 'customers'
id = Column(Integer, primary_key = True)
name = Column(String)
address = Column(String)
email = Column(String)
class Invoice(Base):
__tablename__ = 'invoices'
id = Column(Integer, primary_key = True)
custid = Column(Integer, ForeignKey('customers.id'))
invno = Column(Integer)
amount = Column(Integer)
customer = relationship("Customer", back_populates = "invoices")
Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
Aşağıdaki programı kullanarak birincil kimlik ile sorgulayarak bir Müşteri nesnesi elde ederiz -
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
x = session.query(Customer).get(2)
Örnek tablomuzda, x.name 'Gopal Krishna' olur. Bu x'i oturumdan silelim ve bu ismin geçtiği yeri sayalım.
session.delete(x)
session.query(Customer).filter_by(name = 'Gopal Krishna').count()
Ortaya çıkan SQL ifadesi 0 döndürür.
SELECT count(*)
AS count_1
FROM (
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email
FROM customers
WHERE customers.name = ?)
AS anon_1('Gopal Krishna',) 0
Ancak, x'in ilgili Fatura nesneleri hala oradadır. Aşağıdaki kodla doğrulanabilir -
session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
Burada 10 ve 14, müşteri Gopal Krishna'ya ait fatura numaralarıdır. Yukarıdaki sorgunun sonucu 2'dir, bu da ilgili nesnelerin silinmediği anlamına gelir.
SELECT count(*)
AS count_1
FROM (
SELECT invoices.id
AS invoices_id, invoices.custid
AS invoices_custid, invoices.invno
AS invoices_invno, invoices.amount
AS invoices_amount
FROM invoices
WHERE invoices.invno IN (?, ?))
AS anon_1(10, 14) 2
Bunun nedeni, SQLAlchemy'nin kademeli silme işlemini üstlenmemesidir; onu silmek için bir komut vermeliyiz.
Davranışı değiştirmek için, User.addresses ilişkisinde kademeli seçenekleri yapılandırıyoruz. Devam eden oturumu kapatalım, new declarative_base () kullanalım ve kademeli konfigürasyon dahil adres ilişkisini ekleyerek User sınıfını yeniden bildirelim.
İlişki işlevindeki basamaklı özniteliği, Oturum işlemlerinin ebeveynden alt öğeye nasıl "basamaklandırılması" gerektiğini belirleyen, virgülle ayrılmış bir basamaklı kurallar listesidir. Varsayılan olarak, False, yani "kaydet-güncelle, birleştir" anlamına gelir.
Mevcut kademeler aşağıdaki gibidir -
- save-update
- merge
- expunge
- delete
- delete-orphan
- refresh-expire
Sıklıkla kullanılan seçenek "all, delete-orphan" şeklindedir ve ilgili nesnelerin her durumda üst nesneyle birlikte takip etmesi ve ilişkisi kaldırıldığında silinmesi gerektiğini belirtir.
Bu nedenle, yeniden beyan edilen Müşteri sınıfı aşağıda gösterilmiştir -
class Customer(Base):
__tablename__ = 'customers'
id = Column(Integer, primary_key = True)
name = Column(String)
address = Column(String)
email = Column(String)
invoices = relationship(
"Invoice",
order_by = Invoice.id,
back_populates = "customer",
cascade = "all,
delete, delete-orphan"
)
Aşağıdaki programı kullanarak Gopal Krishna adına sahip Müşteriyi silelim ve ilgili Fatura nesnelerinin sayısını görelim -
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
x = session.query(Customer).get(2)
session.delete(x)
session.query(Customer).filter_by(name = 'Gopal Krishna').count()
session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()
Yukarıdaki komut dosyası tarafından yayınlanan aşağıdaki SQL ile sayı artık 0'dır -
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email
FROM customers
WHERE customers.id = ?
(2,)
SELECT invoices.id
AS invoices_id, invoices.custid
AS invoices_custid, invoices.invno
AS invoices_invno, invoices.amount
AS invoices_amount
FROM invoices
WHERE ? = invoices.custid
ORDER BY invoices.id (2,)
DELETE FROM invoices
WHERE invoices.id = ? ((1,), (2,))
DELETE FROM customers
WHERE customers.id = ? (2,)
SELECT count(*)
AS count_1
FROM (
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email
FROM customers
WHERE customers.name = ?)
AS anon_1('Gopal Krishna',)
SELECT count(*)
AS count_1
FROM (
SELECT invoices.id
AS invoices_id, invoices.custid
AS invoices_custid, invoices.invno
AS invoices_invno, invoices.amount
AS invoices_amount
FROM invoices
WHERE invoices.invno IN (?, ?))
AS anon_1(10, 14)
0