Working with Related Objects
In this chapter, we will focus on the related objects in SQLAlchemy ORM. Now when we create a Customer object, a blank invoice collection will be present in the form of Python List:
- c1 = Customers(name = "Gopal Krishna", address = "Bank Street Hydarebad", email = "gk@gmail.com")
- c1.invoices = [Invoice(invno = 10, amount = 15000), Invoice(invno = 14, amount = 3850)]
- session.add(c1)
- session.commit()
- INSERT INTO customers (name, address, email) VALUES (?, ?, ?)
- ('Gopal Krishna', 'Bank Street Hydarebad', 'gk@gmail.com')
- INSERT INTO invoices (custid, invno, amount) VALUES (?, ?, ?)
- (2, 10, 15000)
- INSERT INTO invoices (custid, invno, amount) VALUES (?, ?, ?)
- (2, 14, 3850)
- testdb=# SELECT * FROM customers;
- id | name | address | email
- ----+---------------+----------------------------+-----------------
- 1 | Ravi Kumar | Station Road Nanded | ravi@gmail.com
- 3 | Rajender Nath | Sector 40, Gurgaon | nath@gmail.com
- 4 | S.M.Krishna | Budhwar Peth, Pune | smk@gmail.com
- 2 | Komal Pande | Banjara Hills Secunderabad | komal@gmail.com
- 5 | Gopal Krishna | Bank Street Hydarebad | gk@gmail.com
- (5 rows)
- testdb=# SELECT * FROM invoices;
- id | custid | invno | amount
- ----+--------+-------+--------
- 1 | 5 | 10 | 15000
- 2 | 5 | 14 | 3850
- (2 rows)
- c2 = [
- Customer(
- name = "Govind Pant",
- address = "Gulmandi Aurangabad",
- email = "gpant@gmail.com",
- invoices = [Invoice(invno = 3, amount = 10000),
- Invoice(invno = 4, amount = 5000)]
- )
- ]
- rows = [
- Customer(
- name = "Govind Kala",
- address = "Gulmandi Aurangabad",
- email = "kala@gmail.com",
- invoices = [Invoice(invno = 7, amount = 12000), Invoice(invno = 8, amount = 18500)]),
- Customer(
- name = "Abdul Rahman",
- address = "Rohtak",
- email = "abdulr@gmail.com",
- invoices = [Invoice(invno = 9, amount = 15000),
- Invoice(invno = 11, amount = 6000)
- ])
- ]
- session.add_all(rows)
- session.commit()
Now that we have two tables, we will see how to create queries on both tables at the same time. To construct a simple implicit join between Customer and Invoice, we can use Query.filter() to equate their related columns together. Below, we load the Customer and Invoice entities at once using this method:
- for c, i in session.query(Customers, Invoice).filter(Customers.id == Invoice.custid).all():
- print ("ID: {} Name: {} Invoice No: {} Amount: {}".format(c.id, c.name, i.invno, i.amount))
- SELECT customers.id AS customers_id, customers.name AS customers_name, customers.address AS customers_address, customers.email AS customers_email, invoices.id AS invoices_id, invoices.custid AS invoices_custid, invoices.invno AS invoices_invno, invoices.amount AS invoices_amount
- FROM customers, invoices
- WHERE customers.id = invoices.custid
Common Relationship Operators
Here we will discuss about the operators which build on relationships. So far we have below data in DB:
- testdb=# SELECT * FROM customers;
- id | name | address | email
- ----+---------------+----------------------------+------------------
- 1 | Ravi Kumar | Station Road Nanded | ravi@gmail.com
- 3 | Rajender Nath | Sector 40, Gurgaon | nath@gmail.com
- 4 | S.M.Krishna | Budhwar Peth, Pune | smk@gmail.com
- 2 | Komal Pande | Banjara Hills Secunderabad | komal@gmail.com
- 5 | Gopal Krishna | Bank Street Hydarebad | gk@gmail.com
- 6 | Govind Kala | Gulmandi Aurangabad | kala@gmail.com
- 7 | Abdul Rahman | Rohtak | abdulr@gmail.com
- (7 rows)
- testdb=# SELECT * FROM invoices;
- id | custid | invno | amount
- ----+--------+-------+--------
- 1 | 5 | 10 | 15000
- 2 | 5 | 14 | 3850
- 3 | 6 | 7 | 12000
- 4 | 6 | 8 | 18500
- 5 | 7 | 9 | 15000
- 6 | 7 | 11 | 6000
- (6 rows)
The above operator is a many-to-one “equals” comparison. The line of code for this operator is as shown below:
- rst = session.query(Customers).filter(Invoice.invno.__eq__(10)).all()
- for r in rst:
- print("Name={} ({})".format(r.name, list(map(lambda e: e.invno, r.invoices))))
- SELECT customers.id
- AS customers_id, customers.name
- AS customers_name, customers.address
- AS customers_address, customers.email
- AS customers_email
- FROM customers, invoices
- WHERE invoices.invno = ?
This operator is a many-to-one “not equals” comparison. The line of code for this operator is as shown below:
- s = session.query(Customer).filter(Invoice.custid.__ne__(2))
- SELECT customers.id
- AS customers_id, customers.name
- AS customers_name, customers.address
- AS customers_address, customers.email
- AS customers_email
- FROM customers, invoices
- WHERE invoices.custid != ?
This operator is used for one-to-many collections and given below is the code for contains():
- rst = session.query(Customers).filter(Customers.name.contains('R')).all()
- 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 LIKE '%%' || %(name_1)s || '%%')
- 2019-06-25 09:27:02,999 INFO sqlalchemy.engine.base.Engine {'name_1': 'R'}
any() operator is used for collections as shown below:
- rst = session.query(Customers).filter(Customers.invoices.any(Invoice.invno==10))
- SELECT customers.id AS customers_id, customers.name AS customers_name, customers.address AS customers_address, customers.email AS customers_email
- FROM customers
- WHERE EXISTS (SELECT 1
- FROM invoices
- WHERE customers.id = invoices.custid AND invoices.invno = %(invno_1)s)
- 2019-06-25 09:31:47,649 INFO sqlalchemy.engine.base.Engine {'invno_1': 10}
This operator is used for scalar references as follows:
- rst = session.query(Invoice).filter(Invoice.customer.has(Customers.name == 'Gopal Krishna'))
- SELECT invoices.id AS invoices_id, invoices.custid AS invoices_custid, invoices.invno AS invoices_invno, invoices.amount AS invoices_amount
- FROM invoices
- WHERE EXISTS (SELECT 1
- FROM customers
- WHERE customers.id = invoices.custid AND customers.name = %(name_1)s)
- 2019-06-25 09:54:35,338 INFO sqlalchemy.engine.base.Engine {'name_1': 'Gopal Krishna'}
Supplement
* Prev - SQLAlchemy ORM - Building Relationship
* Next - SQLAlchemy ORM - Common Relationship Operators
* SQLAlchemy Doc - Using the Session
* SQLAlchemy Doc - Query API
沒有留言:
張貼留言