Jam*_*ire 2 python postgresql sqlalchemy flask flask-sqlalchemy
我正在使用 SQLAlchemy 和 Postgres 创建一个 Flask 应用程序。我对此很陌生,所以我将不胜感激。然而,我的直接问题是在以下模型上构建查询。
from app import db
from sqlalchemy import or_, and_
# Items Table
class Item(db.Model):
__tablename__ = "items"
id = db.Column(db.Integer, primary_key=True)
itemName = db.Column(db.String, unique=True, nullable=False)
measurement = db.Column(db.String, nullable=False)
defaultPrice = db.Column(db.Float, nullable=False)
minimumOrder = db.Column(db.Float, nullable=False)
maximumOrder = db.Column(db.Float, nullable=False)
orders = db.relationship('Order', back_populates='item')
prices = db.relationship('Price', back_populates='item')
def __init__(self, itemName, measurement, defaultPrice,
minimumOrder, maximumOrder):
self.itemName = itemName
self.measurement = measurement
self.defaultPrice = defaultPrice
self.minimumOrder = minimumOrder
self.maximumOrder = maximumOrder
def __repr__(self):
return '<Item {0}>'.format(self.id)
# Users Table
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
fullName = db.Column(db.String, unique=True, nullable=False)
userName = db.Column(db.String, unique=True, nullable=False)
password = db.Column(db.String, nullable=False)
role = db.Column(db.String, nullable=False)
orders = db.relationship('Order', back_populates='user')
prices = db.relationship('Price', back_populates='user')
def __init__(self, fullName, userName, password, role):
self.fullName = fullName
self.userName = userName
self.password = password
self.role = role
def __repr__(self):
return '<User {0}>'.format(self.userName)
# Availability / Price Table
class Price(db.Model):
__tablename__ = 'prices'
id = db.Column(db.Integer, primary_key=True)
userId = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship('User', back_populates='prices')
itemId = db.Column(db.Integer, db.ForeignKey('items.id'))
item = db.relationship('Item', back_populates='prices')
available = db.Column(db.Boolean)
priceMeasurement = db.Column(db.String)
price = db.Column(db.Float)
def __init__(self, userId, itemId, priceMeasurement, price):
self.userId = userId
self.itemId = itemId
self.priceMeasurement = priceMeasurement
self.price = price
def __repr__(self):
return '<Price {0}>'.format(self.price)
# Orders Table
class Order(db.Model):
__tablename__ = 'orders'
id = db.Column(db.Integer, primary_key=True)
userId = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship('User', back_populates='orders')
itemId = db.Column(db.Integer, db.ForeignKey('items.id'))
item = db.relationship('Item', back_populates='orders')
orderQuantity = db.Column(db.Float)
orderMeasurement = db.Column(db.String)
orderPrice = db.Column(db.Float)
orderDelivery = db.Column(db.Date)
orderPlaced = db.Column(db.Date)
def __init__(self, userId, itemId, orderQuantity,
orderMeasurement, orderPrice, orderDelivery, orderPlaced):
self.userId = userId
self.itemId = itemId
self.orderQuantity = orderQuantity
self.orderMeasurement = orderMeasurement
self.orderPrice = orderPrice
self.orderDelivery = orderDelivery
self.orderPlaced = orderPlaced
def __repr__(self):
return '<Order {0}>'.format(self.orderDelivery)
Run Code Online (Sandbox Code Playgroud)
我希望从查询中返回一个与以下查询返回的表类似的表:
SELECT * FROM items
JOIN prices ON prices.itemId=items.id
WHERE prices.userId = 1 AND prices.available = True
LEFT JOIN (
SELECT * FROM orders WHERE orderDelivery = '2017-07-05') as orders
ON orders.itemId=items.id
Run Code Online (Sandbox Code Playgroud)
在 SQLAlchemy 查询中。我将把 userId 和 orderDelivery 变量从路由和会话传递给查询 - @app.route('/user/order/<order_date>')| session['userID']: 登录时建立。
谢谢
如果我理解正确的话,您想要查询(Item, Price, Order)实体元组,其中 Order 来自子查询。这在对象关系教程中从子查询中选择实体下进行了解释。
In [5]: from datetime import date
In [6]: orders_sq = db.session.query(Order).\
...: filter(Order.orderDelivery == date(2017, 7, 5)).\
...: subquery()
In [7]: orders_alias = db.aliased(Order, orders_sq)
In [8]: query = db.session.query(Item, Price, orders_alias).\
...: join(Price).\
...: outerjoin(orders_alias, Item.orders).\
...: filter(Price.userId == 1,
...: Price.available)
Run Code Online (Sandbox Code Playgroud)
以及针对 SQLite 编译时生成的 SQL:
In [9]: print(query)
SELECT items.id AS items_id, items."itemName" AS "items_itemName", items.measurement AS items_measurement, items."defaultPrice" AS "items_defaultPrice", items."minimumOrder" AS "items_minimumOrder", items."maximumOrder" AS "items_maximumOrder", prices.id AS prices_id, prices."userId" AS "prices_userId", prices."itemId" AS "prices_itemId", prices.available AS prices_available, prices."priceMeasurement" AS "prices_priceMeasurement", prices.price AS prices_price, anon_1.id AS anon_1_id, anon_1."userId" AS "anon_1_userId", anon_1."itemId" AS "anon_1_itemId", anon_1."orderQuantity" AS "anon_1_orderQuantity", anon_1."orderMeasurement" AS "anon_1_orderMeasurement", anon_1."orderPrice" AS "anon_1_orderPrice", anon_1."orderDelivery" AS "anon_1_orderDelivery", anon_1."orderPlaced" AS "anon_1_orderPlaced"
FROM items JOIN prices ON items.id = prices."itemId" LEFT OUTER JOIN (SELECT orders.id AS id, orders."userId" AS "userId", orders."itemId" AS "itemId", orders."orderQuantity" AS "orderQuantity", orders."orderMeasurement" AS "orderMeasurement", orders."orderPrice" AS "orderPrice", orders."orderDelivery" AS "orderDelivery", orders."orderPlaced" AS "orderPlaced"
FROM orders
WHERE orders."orderDelivery" = ?) AS anon_1 ON items.id = anon_1."itemId"
WHERE prices."userId" = ? AND prices.available = 1
Run Code Online (Sandbox Code Playgroud)
另外,您也可以简单地将您的声明传递给Query.from_statement一些修复和更改:
In [45]: query2 = db.session.query(Item, Price, Order).\
...: from_statement(db.text("""
...: SELECT * FROM items
...: JOIN prices ON prices.itemId=items.id
...: LEFT JOIN (
...: SELECT * FROM orders WHERE orderDelivery = :orderDelivery) as orders
...: ON orders.itemId=items.id
...: WHERE prices.userId = :userId AND prices.available
...: """)).\
...: params(userId=1, orderDelivery='2017-07-05')
Run Code Online (Sandbox Code Playgroud)
但我建议使用前一种方法,因为它与数据库更加无关。
| 归档时间: |
|
| 查看次数: |
5607 次 |
| 最近记录: |