【问题标题】:How can I get child objects inside parent object using Python and SQL?如何使用 Python 和 SQL 在父对象中获取子对象?
【发布时间】:2021-02-08 04:41:14
【问题描述】:

我正在尝试创建一个基本 API,我有一个名为 orders 的表和另一个名为 order_lines 的表,其中每个订购的产品都有一行,其中一个名为 order_id 的字段对应于订单。在执行 GET 请求时,如何将订单作为父订单并将其中的每个 order_lines 记录作为子数组?我不确定是否需要以某种方式在 SQL 中执行此操作,或者是否可以在 Python 中轻松执行此操作。我只需要大致了解如何提取和构建这些数据。

我的 API GET 请求如下所示:

@app.route('/api/v1/ordertest', methods=['GET'])
def orders_test2():
    # try:
    
    if request.method == 'GET':
        query_parameters = request.args

        id = query_parameters.get('id')
        customer_id = query_parameters.get('customer_id')

        query = '''
                    SELECT 
                        o.*,
                        ol.product_id, 
                        p.name, 
                        ol.quantity, 
                        p.price as price, 
                        round((p.price * ol.quantity), 2) as total_price
                    FROM orders o
                    join order_lines ol
                    on o.id = ol.order_id
                    join products p
                    on ol.product_id = p.id
                    WHERE o.
                '''
        to_filter = []

        if id:
            query += 'id=? AND'
            to_filter.append(id)
        if customer_id:
            query += 'customer_id=? AND'
            to_filter.append(customer_id)

        if not (id or customer_id):
            return page_not_found(404)

        query = query[:-4] + ';'

        conn = sqlite3.connect(db)
        conn.row_factory = dict_factory
        cur = conn.cursor()

        results = cur.execute(query, to_filter).fetchall()

        return jsonify(results)

执行/api/v1/ordertest?id=1 会返回我想要的所有数据,但它包含每个产品对象中列出的订单表中的信息。

[
  {
    "created_at": "2020-11-12 00:08:32", 
    "customer_id": 1, 
    "id": 1, 
    "name": "plum", 
    "price": 0.3, 
    "product_id": 4, 
    "quantity": 2, 
    "status": "delivered", 
    "total_price": 0.6, 
    "updated_at": "2021-02-05 18:41:20"
  }, 
  {
    "created_at": "2020-11-12 00:08:32", 
    "customer_id": 1, 
    "id": 1, 
    "name": "salmon", 
    "price": 6.76, 
    "product_id": 20, 
    "quantity": 4, 
    "status": "delivered", 
    "total_price": 27.04, 
    "updated_at": "2021-02-05 18:41:20"
  }, 
  {
    "created_at": "2020-11-12 00:08:32", 
    "customer_id": 1, 
    "id": 1, 
    "name": "mint chocolate bar", 
    "price": 2.01, 
    "product_id": 30, 
    "quantity": 3, 
    "status": "delivered", 
    "total_price": 6.03, 
    "updated_at": "2021-02-05 18:41:20"
  }
]

但是,我希望数据看起来像这样,其中具有匹配 order_id 的每个 order_lines 行都位于主对象内:

[
    {
      "created_at": "2020-11-12 00:08:32", 
      "customer_id": 1, 
      "id": 1, 
      "status": "delivered", 
      "updated_at": "2021-02-05 18:41:20",
      "products": 
      {
          "name": "plum", 
          "price": 0.3, 
          "product_id": 4, 
          "quantity": 2,
          "total_price": 0.6
          }, 
      {
          "name": "salmon", 
          "price": 6.76, 
          "product_id": 20, 
          "quantity": 4, 
          "total_price": 27.04
      }, 
      {
          "name": "mint chocolate bar", 
          "price": 2.01, 
          "product_id": 30, 
          "quantity": 3, 
          "total_price": 6.03
        }
    }
  ]

【问题讨论】:

  • 考虑使用像SQLAlchemy这样的ORM
  • 在生产中,您通常会写出每个列名(而不是使用 *),因为它用于文档,并确保代码不会仅仅因为将新列添加到您使用的表中而改变行为.如果主键和副键使用相同的名称,则可以使用自然关节,这意味着您不需要指定所有样板关节条件。 IE。而不是 orders.id 使用 orders.order_id 作为你的主键。

标签: python sql api flask


【解决方案1】:

管理一个数据库,应该通过SQL管理系统,如MySQL、SQLite...你可以通过将它们的python库导入你的代码来使用它们来执行SQL查询。 您的问题可以通过以下方式解决:

    SELECT column_name(s)
    FROM table1
    INNER JOIN table2
    ON table1.column_name = table2.column_name;

【讨论】:

  • 嗨,我确实在我的数据库中进行了这样的设置,但是当执行这样的连接时,它会从表 1 的每一行返回表 2 数据的数据,这并不理想。我只想让表 1 中的数据在顶部显示一次,然后将表 2 中的每一行列为子项
  • 在这种情况下,您可以使用 SELECT UNION。
【解决方案2】:

我建议您阅读 REST(ful) API,因为它会让您了解如何处理分层数据(GraphQL 将是另一种方式)。正如您所提到的,您可以有两个端点,也可以有一个端点:

GET /orders?order_id=1 or
GET /orders/1

可能会返回类似这样的内容(csv、json 也是一个不错的选择,但会给示例增加更多噪音):

item,quantity,price
Bicycle,1,$500
Helmet,1,$125

如果您想使用两个端点,它可以改为返回指向每个订单商品的链接:

/order_line/27
/order_line/42

另一个设计选择是像这样在 URL 中编码数据的层次结构:

 /order/1/order_line/27
 /order/1/order_line/42

然后您的客户获取这些网址中的每一个 提取附加信息。这会产生很大的开销,因此对于这样的小数据,您通常会将数据嵌入到单个端点中。

当您编写代码时,您将提取此 1 中的 order_id,并在此 SQL 中获取您的数据库可能是的值:

select item, quantity, price from line_items where order_id = 1

(确保将变量与您决定使用的任何数据库 API 绑定)。相关表格可能如下所示:

create table orders (
   order_id int primary key,
);

create table order_lines (
   order_line_id int primary key,
   order_id int not null references orders (order_id),
);

【讨论】:

  • 嗨,在您的示例中,我获取了对应 id 的每一行 order_lines,但我也不会从订单中获取信息。我希望订单数据成为父对象,然后关联的每一行 order_lines 作为子对象存在于其中。我已经用我的代码和 JSON 更新了我的问题以获得更好的上下文
  • 没有魔法,Cole,您编写了一个函数,将数据库中的数据转换为您需要的格式。您的结果变量将每个行项目有一行,这意味着您可以从第一行 `order = [ 'created_at': results[0]['created_at'], ...] 获取订单详细信息。 orders[0]['products'] 是您的订单项,因此您可以生成带有列表理解的订单项。
猜你喜欢
  • 2022-12-15
  • 1970-01-01
  • 2021-01-25
  • 2020-04-14
  • 2017-11-23
  • 1970-01-01
  • 2023-03-14
  • 2021-07-21
  • 2020-09-11
相关资源
最近更新 更多