flask_sqlalchemy 返回对象 转化

本文介绍如何使用SQLAlchemy的ORM特性进行数据库操作,并通过自定义编码器将查询结果转换为JSON格式,便于前端展示或API响应。文章详细解释了AlchemyEncoder类的设计原理和使用方法,展示了如何从数据库中获取所有用户数据并将其序列化。
返回结果 [<apps.models.test.index.User object at 0x000001D2EDD91208>, <apps.models.test.index.User object at 0x000001D2EDA666D8>, <apps.models.test.index.User object at 0x000001D2EDD62358>]

返回数据类型 <class 'list'>

<apps.models.test.index.User object at 0x000001D2EDA666D8>

<class 'apps.models.test.index.User'>

处理结果 [{"creact_time": null, "id": 1, "name": "root", "password": "123456", "query": null, "query_class": null, "status": 1}, {"creact_time": null, "id": 2, "name": "An", "password": "123456", "query": null, "query_class": null, "status": 1}, {"creact_time": "2019-10-31 11:12:08.041", "id": 4, "name": "admin", "password": "123456", "query": null, "query_class": null, "status": 1}]

处理类型 <class 'str'>

再次处理 [{'creact_time': None, 'id': 1, 'name': 'root', 'password': '123456', 'query': None, 'query_class': None, 'status': 1}, {'creact_time': None, 'id': 2, 'name': 'An', 'password': '123456', 'query': None, 'query_class': None, 'status': 1}, {'creact_time': '2019-10-31 11:12:08.041', 'id': 4, 'name': 'admin', 'password': '123456', 'query': None, 'query_class': None, 'status': 1}]

再次处理类型 <class 'list'>

An

工具类

from sqlalchemy.ext.declarative import DeclarativeMeta
import json
class AlchemyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # an SQLAlchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                data = obj.__getattribute__(field)
                try:
                    json.dumps(data) # this will fail on non-encodable values, like other classes
                    fields[field] = data
                except TypeError:
                    fields[field] = None
            # a json-encodable dict
            return fields
        return json.JSONEncoder.default(self, obj)

使用

from apps.models.test.index import User # model(自行替换)
from utils.AlchemyEncoder import AlchemyEncoder # (路径自行替换)
import json
class Reptile():
    def test():
        users = User.query.all() # 获取表全部数据(自行替换)
        arr = json.dumps(users, cls=AlchemyEncoder)
        
        print(users)
        print(type(users))
        print(users[1])
        print(type(users[1]))

        print(arr)
        print(type(arr))

        a = json.loads(arr)
        print(a)
        print(type(a))
        print(a[1]['name'])

 

<think>好的,我需要帮助用户将给定的SQL查询转换为Flask SQLAlchemy的查询形式。用户提供的SQL是:select image_id from parts where type='{typ}' and article_no='{article_no}' and article_no_zh='{article_no_zh}';。目标是用Part.query.filter来实现。 首先,我要确认用户使用的是Flask-SQLAlchemy的模型结构。假设用户已经定义了一个名为Part的模型,对应数据库中的parts表,并且该模型包含type、article_no、article_no_zh和image_id字段。这是基础,如果模型字段不匹配,查询会出错,所以需要确保模型正确。 接下来,用户提到的Part.query.filter方法,这里需要注意Flask-SQLAlchemy的查询语法。正确的做法是使用filter_by或者filter方法。但根据用户的问题,他们明确要求使用filter,而不是filter_by。因为filter_by接受关键字参数,而filter需要使用表达式,比如模型字段的比较。 原来的SQL中的条件都是等值查询,三个条件用AND连接。在SQLAlchemy中,多个条件传递给filter方法时,默认会用AND连接。因此,可以将这三个条件依次添加到filter中。 所以,正确的查询应该是:Part.query.with_entities(Part.image_id).filter(Part.type == typ, Part.article_no == article_no, Part.article_no_zh == article_no_zh).all()。这里需要注意几点: 1. 使用with_entities来指定只选择image_id字段,这样返回的结果是image_id的列表,而不是整个Part对象。如果不使用with_entities,查询会返回Part对象,但用户只需要image_id,所以这样更高效。 2. filter中的每个条件都是模型字段与变量的比较。变量typ、article_no、article_no_zh需要已经在上下文中定义,并且传入正确的值。 3. 最后的.all()会执行查询并返回所有结果。如果只需要第一个结果,可以使用.first()。 然后,用户可能遇到的问题包括字段名是否正确,变量是否有正确的值,以及查询结果的处理。例如,如果模型中的字段名与数据库中的列名不一致,需要使用__tablename__或列定义来映射。另外,如果变量未正确传递,可能导致查询条件不匹配,返回空结果。 根据引用[3]中的示例,用户在使用filter_by时遇到了类型错误,但在这里使用filter应该没有问题,只要条件正确。同时,确保变量被正确传递,比如typ等参数应该是字符串类型。 最后,测试这个查询是否返回预期的image_id,可以通过打印查询生成的SQL语句来调试,使用str(Part.query.filter(...).statement)来查看实际的SQL是否符合预期。</think>要将SQL查询`select image_id from parts where type='{typ}' and article_no='{article_no}' and article_no_zh='{article_no_zh}';`转换为Flask SQLAlchemy的查询形式,可以按照以下步骤操作: ### 步骤说明 1. **确保模型定义正确** 假设已定义`Part`模型对应数据库表`parts`,且包含字段`type`、`article_no`、`article_no_zh`和`image_id`: ```python class Part(db.Model): __tablename__ = 'parts' image_id = db.Column(db.Integer, primary_key=True) type = db.Column(db.String(50)) article_no = db.Column(db.String(50)) article_no_zh = db.Column(db.String(50)) ``` 2. **构建查询条件** 使用`filter()`方法添加多个条件,默认以`AND`逻辑连接: ```python result = Part.query.with_entities(Part.image_id).filter( Part.type == typ, Part.article_no == article_no, Part.article_no_zh == article_no_zh ).all() ``` 3. **获取结果** `.all()`返回包含所有结果的列表,`.first()`返回第一个结果: ```python image_ids = [row.image_id for row in result] # 提取image_id列表 ``` ### 完整代码示例 ```python # 假设typ, article_no, article_no_zh已赋值 query_result = Part.query.with_entities(Part.image_id).filter( Part.type == typ, Part.article_no == article_no, Part.article_no_zh == article_no_zh ).all() # 提取image_id列表 image_ids = [result.image_id for result in query_result] ``` ### 注意事项 - 若字段名与数据库列名不一致,需通过`db.Column(name='column_name')`显式指定 - 变量`typ`、`article_no`、`article_no_zh`需提前定义或从请求参数获取 - 使用`filter`而非`filter_by`时,需通过`Model.column == value`明确列对象[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

An_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值