Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用python api代码仅更新postgres表中json类型列的1个属性_Python_Postgresql_Sqlalchemy - Fatal编程技术网

如何使用python api代码仅更新postgres表中json类型列的1个属性

如何使用python api代码仅更新postgres表中json类型列的1个属性,python,postgresql,sqlalchemy,Python,Postgresql,Sqlalchemy,我有一个名为products的postgresql(v.9.5)表,使用sqlalchemy core定义为: products = Table("products", metadata, Column("id", Integer, primary_key=True), Column("name", String, nullable=False, unique=True), Column("de

我有一个名为products的postgresql(v.9.5)表,使用sqlalchemy core定义为:

products = Table("products", metadata,
                 Column("id", Integer, primary_key=True),
                 Column("name", String, nullable=False, unique=True),
                 Column("description", String),
                 Column("list_price", Float),
                 Column("xdata", JSON))
假设表中的日期添加如下:

id |    name    |        description        | list_price |             xdata              
----+------------+---------------------------+------------+--------------------------------
 24 | Product323 | description of product332 |       6000 | [{"category": 1, "uom": "kg"}]
def edit_product(product_id):
    if 'id' in session:
        exist_data = {}
        mkeys = []
        s = select([products]).where(products.c.id == product_id)
        rs = g.conn.execute(s)
        if rs.rowcount == 1:
            data = request.get_json(force=True)
            for r in rs:
                exist_data = dict(r)
            try:
                print exist_data, 'exist_data'
                stmt = products.update().values(data).\
                       where(products.c.id == product_id)
                rs1 = g.conn.execute(stmt)
                return jsonify({'id': "Product details modified"}), 204
            except Exception, e:
                print e
                return jsonify(
                    {'message': "Couldn't modify details / Duplicate"}), 400

    return jsonify({'message': "UNAUTHORIZED"}), 401
使用API编辑代码,如下所示:

id |    name    |        description        | list_price |             xdata              
----+------------+---------------------------+------------+--------------------------------
 24 | Product323 | description of product332 |       6000 | [{"category": 1, "uom": "kg"}]
def edit_product(product_id):
    if 'id' in session:
        exist_data = {}
        mkeys = []
        s = select([products]).where(products.c.id == product_id)
        rs = g.conn.execute(s)
        if rs.rowcount == 1:
            data = request.get_json(force=True)
            for r in rs:
                exist_data = dict(r)
            try:
                print exist_data, 'exist_data'
                stmt = products.update().values(data).\
                       where(products.c.id == product_id)
                rs1 = g.conn.execute(stmt)
                return jsonify({'id': "Product details modified"}), 204
            except Exception, e:
                print e
                return jsonify(
                    {'message': "Couldn't modify details / Duplicate"}), 400

    return jsonify({'message': "UNAUTHORIZED"}), 401

假设我只想修改表的扩展数据列中的“category”值,而不干扰“uom”属性及其值,那么实现它的最佳方法是什么?我尝试了“for循环”来获取现有值的属性,然后使用传递的属性值检查要更新的更改。我相信还有比这更好的办法。请使用简化此操作所需的更改进行还原。Postgresql提供了用新值替换
jsonb
部分的功能。您的专栏使用的是
json
类型,但是一个简单的cast就可以解决这个问题

from sqlalchemy.dialects.postgresql import JSON, JSONB, array
import json

def edit_product(product_id):
    ...

    # If xdata is present, replace with a jsonb_set() function expression
    if 'xdata' in data:
        # Hard coded path that expects a certain structure
        data['xdata'] = func.jsonb_set(
            products.c.xdata.cast(JSONB),
            array(['0', 'category']),
            # A bit ugly, yes, but the 3rd argument to jsonb_set() has type
            # jsonb, and so the passed literal must be convertible to that
            json.dumps(data['xdata'][0]['category'])).cast(JSON)

您还可以设置一个通用帮助器,该帮助器创建对
jsonb_set()
的嵌套调用,给定一些结构:

import json

from sqlalchemy.dialects.postgresql import array

def to_jsonb_set(target, value, create_missing=True, path=()):
    expr = target

    if isinstance(value, dict):
        for k, v in value.items():
            expr = to_jsonb_set(expr, v, create_missing, (*path, k))

    elif isinstance(value, list):
        for i, v in enumerate(value):
            expr = to_jsonb_set(expr, v, create_missing, (*path, i))

    else:
        expr = func.jsonb_set(
            expr,
            array([str(p) for p in path]),
            json.dumps(value),
            create_missing)

    return expr

但这可能太过分了。

Iiuc,在UPDATE语句中使用
jsonb_set()
。你的问题有点轻于实际细节,比如什么是
data
like.data是在curlcurl-bcookies.txt-X PUT-d'{“list_price”:70000.00,“xdata”:[{“category”:5}]}'-H'内容类型:application/json中传递的值:我如何仅使用sqlalchemy核心中的jsonb_集?相关: