`
sodler
  • 浏览: 14659 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

queryset 的F( )表达式

 
阅读更多

class F

一个 F()对象代表了一个model的字段值或注释列。使用它就可以直接参考model的field和执行数据库操作而不用再把它们查询出来放到python内存中。作为代替,Django使用 F()对象生成一个SQL表达式,来描述数据库层级所需要的操作,这些通过一个例子可以很容易的理解。往常,在数据库中获取一个数据会这样做:

(终端实验)

>>>q = OB.objects.filter(name='Tintin')
>>>q[0].number += 1
(值不变)

或者:

q = OB.objects.get(name='Tintin')
q.number += 1(值增加,但是并未保存进数据库,加上q.save()即可)

 

这里,我们把 q 的 number 属性值从数据库取出放到内存中并用我们熟悉的python运算符操作它,最后再把它保存到数据库。然而,还可以这样做:

 

from django.db.models import F
 
q = OB.objects.get(name='Tintin')
q.number = F('number') + 1

 

虽然 q[0].number = F('number') + 1 看起来像一个正常的Python分配值赋给一个实例属性,事实上这是一个描述数据库操作的SQL概念。

>>>q.number
<CombinedExpression(联合表达): F(number) + Value(1)>
下面有具体例子

 

当Django遇到 F()实例,它覆盖了标准的Python运算符创建一个封装的SQL表达式。在这个例子中,q[0].number就代表了一个指示数据库对该字段进行增量的命令。

无论q[0].number的值是或曾是什么,Python完全不知道,这完全是由数据库去处理的。所有的Python,通过Django的F() 类,只是去创建SQL语法参考字段和描述操作。

 

为了获得用这种方法保存的新值,此对象应重新加载:

q = OB.objects.get(name='Tintin')

和上面单独实例的操作一样, F()配合 update()可以应用于对象实例的 QuerySets这减少了我们上面使用的两个查询 get() 和 save() 只需要使用如下方式:

>>> q = UserItem.objects.filter(name='雪碧')
>>> q.update(number=F('number')+1)
1
>>> q[0].number
Decimal('6')

我们可以使用update()方法批量地增加多个对象的字段值。这比先从数据库查询后,通过循环一个个增加,并一个个保存要快的很多。

UserItem.objects.all().update(number=F('number')+1)

F()表达式的效率上的优点主要体现在

1.直接通过数据库操作而不是Python

2.减少数据库查询次数

 

使用 F() 的另一个好处是通过数据库而不是Python来更新字段值以避免竞态条件。

如果两个Python线程执行上面第一个例子中的代码,一个线程可能在另一个线程刚从数据库中获取完字段值后获取、增加、保存该字段值。第二个线程保存的值将会基于原始字段值;第一个线程的工作将会丢失。如果让数据库对更新字段负责,这个过程将变得更稳健:它将只会在 save() 或 update()执行时根据数据库中该字段值来更新字段,而不是基于实例之前获取的字段值。同时F()在查询集和过滤器中也十分有用,它使得使用条件通过字段值而不是Python值过滤一组对象变得可能,例如:

q = OB.objects.filter(number=F('pro_number'))

 

直接获取了实际数量大于优惠数量的商品信息,不需要获取两个数量之后比较再存入新数组,同时搭配查询集的选择器能进行更多方便的操作。

 

F()可用于通过将不同字段与算术相结合来在模型上创建动态字段:

q = OB.objects.annotate(new_number=F('number') - F('pro_number')){annotate方法添加注释}

如果你组合的字段是不同类型,你需要告诉Django将返回什么类型的字段。由于F()不直接支持output_field,您需要使用Expression Wrapper

{Expression Wrapper简单地包围另一个表达式,并提供对其他表达式可能不可用的属性(例如output_field)的访问。当对 F() 的 annotations 中描述的不同类型的F()表达式使用算术时,必须使用 Expression Wrapper, class ExpressionWrapper(expression, output_field) }

from django.db.models import DateTimeField, ExpressionWrapper, F
 
OB.objects.annotate(
    expires=ExpressionWrapper(
        F('active_a') + F('active_b'), output_field=DateTimeField()))

 

分享到:
评论

相关推荐

    django框架F&Q 聚合与分组操作示例

    **一、F表达式** F表达式是Django提供的一个强大的工具,用于在查询中引用模型的字段。它允许你在比较操作中使用模型的字段,而无需先从数据库中获取它们。例如: ```python from django.db.models import F # ...

    详解Django的model查询操作与查询性能优化

    F表达式可以用来比较模型字段的值,而Q对象则可以构建复杂的查询条件。 6. 使用数据库索引。索引能够显著提高查询速度,特别是对于大数据集而言,建立适当索引是提高查询效率的重要手段。 7. 对于大数据集的查询,...

    django 利用Q对象与F对象进行查询的实现

    Q对象是Django ORM提供的一种高级查询工具,它可以让你构建复杂的查询表达式,支持AND、OR和NOT操作。例如: 1. AND关系:`Book.objects.filter(id__gt=2, bread__gt=20)` 或者 `Book.objects.filter(Q(bread__gt=...

    Django的ORM常用查询操作总结.rar

    - 使用`Q对象`可以构建复杂的查询条件,例如`Q(age__gt=30) & Q(gender='F')`表示年龄大于30且性别为女的用户。 - `exclude()`也可以接受Q对象,如`exclude(Q(age__lt=18) | Q(is_active=False))`排除未成年或未...

    Django面试题.pdf_python面试

    在Django ORM中,F对象可以创建一个字段间的表达式,允许对同一模型实例中的两个字段进行比较。而Q对象则用于构建复杂的查询条件,可以实现条件的AND、OR和NOT逻辑,从而使得构建动态查询变得更加灵活。 **values和...

    使用Django实现把两个模型类的数据聚合在一起

    在Django中,要聚合这两个模型类的数据,你可以使用查询集(QuerySet)的方法,特别是`filter()`方法配合`F()`表达式。`F()`对象允许你在查询中引用模型的字段,而无需提供实际的值。例如,如果模型A的`bookid`字段...

    Django 7天教学大纲1

    - **查询操作**:学习如何进行基本的查询,如查询所有、单个对象,设置过滤条件,使用查询表达式,理解QuerySet API,进行关联查询,排序和限制结果集。 - **模型的修改与删除**:学习如何更新和删除模型数据,以及...

    Django的性能优化实现解析

    2. **利用`F()`表达式**:在同一个模型内,使用`F()`表达式进行字段间的运算,避免Python处理,提高效率。 3. **使用`annotate()`**:对数据库进行聚合操作,如求和、平均值等,避免在Python层面处理大数据。 4. *...

    Django中Aggregation聚合的基本使用方法

    Django的Aggregation功能还包括其他聚合函数,如`Sum`(求和)、`Count`(计数)、`StdDev`(标准差)、`Variance`(方差)等,以及更高级的聚合操作,如`GroupBy`和`F`表达式,它们可以用来创建更复杂的查询,如...

    python入门到高级全栈工程师培训 第3期 附课件代码

    07 三元运算,列表解析,生成器表达式 第19章 01 生成器函数 02 生成器函数的好处 03 母鸡下蛋的传说 04 生成器特性阐释 05 生产者消费者模型 06 第三次作业讲解 第20章 01 上节课回顾 02 装饰器基本理论 03 高...

Global site tag (gtag.js) - Google Analytics