关于query.filter()的一些常用的方法

本文介绍使用SQLAlchemy进行数据库查询的方法,包括条件过滤、模糊搜索、集合操作等高级查询技巧,并展示了如何利用Python表达式实现复杂查询逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

equals:   

query.filter(User.name=='ed')

not equals:

query.filter(User.name!='ed')

like:

query.filter(User.name.like('%ed%'))

in:

query.filter(User.name.in_(['ed','wen','jask']))

not in:

query.filter(~User.name.in_(['ed','wen','jask']))

in null:

 query.filter(User.name==None)

is not null:

query.fillter(User.name!=None)

and:

query.filter(and_(User.name=='ed',Username=='ed jones'))

or:

query.filter(or_(User.name= 'ed',User.name=='wendy')

match:

query.filter(User.name.match('wendy'))

match() 使用特定于数据库的匹配或包含函数;它的行为会随着后端而变化,并且在诸如SQLite这样的一些后端是不可用的。

all(): 

    返回一个列表

first():

    返回至多一个结果,而且以单项形式,而不是只有一个元素的tuple形式返回这个结果

one():

    返回且仅返回一个查询结果。当结果的数量不足一个或者多于一个时会报错

one_or_one():

    当结果数量为0时返回None, 多于1个时报错

scalar():

    成功则返回该行的第一列的列号

text():

>>> from sqlalchemy import text
sql>>> for user in session.query(User).\
...             filter(text("id<224")).\
...             order_by(text("id")).all():
...     print(user.name)

ed
wendy
mary
fred

params():传递参数

>>> session.query(User).filter(text("id<:value and name=:name")).\
...     params(value=224, name='fred').order_by(User.id).one()

<User(name='fred', fullname='Fred Flinstone', password='blah')>

from_statement():直接使用完整的SQL语句,但是要注意将表名和列名写正确

>>> session.query(User).from_statement(
...                     text("SELECT * FROM users where name=:name")).\
...                     params(name='ed').all()

[<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>]

count():返回符合条件的总数

>>> session.query(User).filter(User.name.like('%ed')).count()

2

func_count():可以直接指出要测次数的某一项

>>> from sqlalchemy import func
sql>>> session.query(func.count(User.name), User.name).group_by(User.name).all()

[(1, u'ed'), (1, u'fred'), (1, u'mary'), (1, u'wendy')]

 

<think>好的,我现在需要解释这两行代码的区别:一个是使用`cls.attribute["obj_name"]`,另一个是直接使用`cls.obj_name`。首先,我得理解这两者的结构。 用户提到这是在一个类方法中,可能涉及ORM,比如SQLAlchemy。在SQLAlchemy中,模型类通常会定义一些列属性,比如`obj_name = Column(String)`。所以直接使用`cls.obj_name`应该是指向这个列属性的正确方式。 那`cls.attribute["obj_name"]`呢?这可能表示`attribute`是一个类似字典的属性,里面存储了各个字段的映射。比如,如果类有一个`attribute`类属性,它是一个包含各个列名的字典,那么通过键访问就可以得到对应的列对象。例如,`attribute = {"obj_name": obj_name_column}`,这样`cls.attribute["obj_name"]`就等同于`cls.obj_name`。 接下来,我需要考虑这两种方式的区别。直接访问属性通常更直接,效率也可能更高,因为不需要经过字典查找。而使用字典的方式可能更灵活,特别是当列名动态生成或在运行时确定时,可以通过字符串来访问对应的属性。 另一个方面是代码的可维护性。直接使用`cls.obj_name`更清晰,符合常见的ORM用法。而使用字典可能需要额外的维护,确保字典中的键和实际的属性名保持一致,否则容易出错。 可能存在的错误情况:如果`cls`没有`attribute`属性,或者`attribute`字典中没有`"obj_name"`这个键,那么第一种方式会抛出`KeyError`或`AttributeError`。而第二种方式如果`obj_name`不存在,同样会报错,但这种情况较少,因为通常ORM的列属性是明确声明的。 还有,是否涉及到关系或其他复杂结构?比如,`attribute`可能关联的是其他类型的属性,比如混合属性或复合列,这时候使用字典可能有特殊处理。但通常情况下,直接访问属性更常见。 总结的话,两种方式在功能上可能等效,但实现方式不同,适用场景不同。直接访问更直接高效,字典方式更灵活但需要额外结构支持。</think>这两行代码的核心区别在于**属性访问方式**和**底层实现逻辑**,主要涉及ORM(对象关系映射)框架中过滤条件的构建方式: --- ### 一、代码结构解析 1. **字典映射方式** `query = query.filter(cls.attribute["obj_name"] == filters["obj_name"])` - 假设`cls.attribute`是一个**预定义的字典**,存储了模型属性与数据库字段的映射关系 - 通过键`"obj_name"`从字典中**动态获取模型属性**,属于间接访问 - 需要确保`cls.attribute`中存在`"obj_name"`键,否则会抛出`KeyError` 2. **直接属性访问方式** `query = query.filter(cls.obj_name == filters["obj_name"])` - 直接通过类属性`obj_name`访问模型字段,属于显式访问 - 要求`obj_name`必须是**类中明确定义的属性**(如SQLAlchemy的`Column`对象) - 若`obj_name`未定义会直接抛出`AttributeError` --- ### 二、关键差异对比 | 特性 | 字典映射方式 | 直接属性访问方式 | |---------------------|-----------------------------------|---------------------------| | **灵活性** | 高(可通过字符串动态配置字段) | 低(需硬编码属性名) | | **可读性** | 较差(需理解字典结构) | 好(直观显示字段来源) | | **错误风险** | 依赖字典完整性(易出现`KeyError`) | 依赖类定义完整性(`AttributeError`) | | **典型应用场景** | 需要动态生成查询条件的框架封装 | 常规ORM查询操作 | --- ### 三、底层原理示例(以SQLAlchemy为例) 1. **字典方式等价逻辑** ```python column = getattr(cls, 'attribute')["obj_name"] # 从字典获取列对象 query = query.filter(column == value) ``` 2. **直接访问等价逻辑** ```python query = query.filter(cls.obj_name == value) # 直接使用类属性 ``` --- ### 四、选择建议 - 优先使用**直接属性访问**:除非有动态字段需求,否则更安全直观 - 字典方式适用场景:需要实现类似`filter_by(**kwargs)`的动态查询封装时 > ⚠️ 如果发现代码中混合使用这两种方式,建议统一风格以提升可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值