SQLAlchemy ORM - संबंधित वस्तुओं को हटाना

एक ही टेबल पर डिलीट ऑपरेशन करना आसान है। आपको बस इतना करना है कि एक सत्र से मैप की गई कक्षा की एक वस्तु को हटाना और कार्रवाई करना है। हालाँकि, एकाधिक संबंधित तालिकाओं पर हटाए गए ऑपरेशन थोड़ा मुश्किल है।

हमारे Sales.db डेटाबेस में, ग्राहक और चालान क्लासेस को ग्राहक के साथ मैप किया जाता है और एक से कई प्रकार के संबंधों के साथ इनवॉइस टेबल दिया जाता है। हम ग्राहक ऑब्जेक्ट को हटाने और परिणाम देखने का प्रयास करेंगे।

एक त्वरित संदर्भ के रूप में, ग्राहक और चालान कक्षाओं की परिभाषाएँ नीचे दी गई हैं -

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")

हम एक सत्र सेटअप करते हैं और नीचे दिए गए प्रोग्राम का उपयोग करके प्राथमिक आईडी के साथ क्वेरी करके एक ग्राहक वस्तु प्राप्त करते हैं -

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
x = session.query(Customer).get(2)

हमारी नमूना तालिका में, x.name 'गोपाल कृष्ण' होता है। आइए हम इस x को सत्र से हटाते हैं और इस नाम की घटना को गिनते हैं।

session.delete(x)
session.query(Customer).filter_by(name = 'Gopal Krishna').count()

परिणामस्वरूप SQL एक्सप्रेशन 0 पर वापस आ जाएगा।

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

हालाँकि, x के संबंधित इनवॉइस ऑब्जेक्ट अभी भी हैं। यह निम्नलिखित कोड द्वारा सत्यापित किया जा सकता है -

session.query(Invoice).filter(Invoice.invno.in_([10,14])).count()

यहां 10 और 14 ग्राहक गोपाल कृष्ण के चालान नंबर हैं। उपरोक्त क्वेरी का परिणाम 2 है, जिसका अर्थ है कि संबंधित ऑब्जेक्ट हटाए नहीं गए हैं।

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

इसका कारण यह है कि SQLAlchemy कैस्केड के विलोपन को ग्रहण नहीं करता है; हमें इसे हटाने के लिए एक कमांड देनी होगी।

व्यवहार को बदलने के लिए, हम User.addresses संबंध पर कैस्केड विकल्प कॉन्फ़िगर करते हैं। चल रहे सत्र को बंद करते हैं, नए घोषणात्मक_बेस () का उपयोग करते हैं और उपयोगकर्ता वर्ग को फिर से परिभाषित करते हैं, कैस्केड कॉन्फ़िगरेशन सहित पतों के संबंध में जोड़ते हैं।

संबंध समारोह में कैस्केड विशेषता कैस्केड नियमों की अल्पविराम से अलग की गई सूची है जो यह निर्धारित करती है कि माता-पिता से बच्चे तक सत्र संचालन कैसे "कैस्केड" किया जाना चाहिए। डिफ़ॉल्ट रूप से, यह गलत है, जिसका अर्थ है कि यह "सेव-अपडेट, मर्ज" है।

उपलब्ध कैस्केड इस प्रकार हैं -

  • save-update
  • merge
  • expunge
  • delete
  • delete-orphan
  • refresh-expire

अक्सर इस्तेमाल किया जाने वाला विकल्प "सभी, हटाना-अनाथ" है यह इंगित करने के लिए कि संबंधित वस्तुएं सभी मामलों में मूल वस्तु के साथ पालन करें, और डी-संबद्ध होने पर हटा दी जाएं।

इसलिए redeclared ग्राहक वर्ग नीचे दिखाया गया है -

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" 
   )

नीचे दिए गए प्रोग्राम का उपयोग करके ग्राहक को गोपाल कृष्ण नाम से हटाते हैं और इसकी संबंधित इनवॉइस ऑब्जेक्ट्स की गिनती देखते हैं -

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()

गिनती अब 0 से ऊपर स्क्रिप्ट द्वारा उत्सर्जित एसक्यूएल के साथ है -

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