(六)Django进阶之路 QuerySet 上

from django.db.models import Count, F, Value
from django.db.models.functions import Length, Upper

F表达式的一般用法

# 找到员工比椅子多的公司。
Company.objects.filter(num_employees__gt=F('num_chairs'))

# 找到雇员至少是原来两倍的公司,下面的两个查询集的执行结果是等效的。
Company.objects.filter(num_employees__gt=F('num_chairs') * 2)
Company.objects.filter(
    num_employees__gt=F('num_chairs') + F('num_chairs'))

F表达式的组合用法

# 每个公司需要多少张椅子来容纳所有的员工?
>>> company = Company.objects.filter(
...    num_employees__gt=F('num_chairs')).annotate(
...    chairs_needed=F('num_employees') - F('num_chairs')).first()
>>> company.num_employees
120
>>> company.num_chairs
50
>>> company.chairs_needed
70

Upper表达式的用法

# 使用 Upper 的表达式创建一个公司记录。
>>> company = Company.objects.create(name='Google', ticker=Upper(Value('goog')))
# 如果需要访问字段,请确保刷新它。
>>> company.refresh_from_db()
>>> company.ticker
'GOOG'

聚合与F的配合使用

  • 用 Annotate 模型方法以及 经过聚合方法 aggregated 得出的值构成一个新的字段别名,如下两段代码是等效的
Company.objects.annotate(num_products=Count('products'))
Company.objects.annotate(num_products=Count(F('products')))
  • Aggregates 还可以包含复杂的计算

Company.objects.annotate(num_offerings=Count(F('products') + F('services')))
  • 表达式也可以直接在order_by()中使用
Company.objects.order_by(Length('name').asc())
Company.objects.order_by(Length('name').desc())
  • 使用双下划线查找语法。
from django.db.models import CharField
from django.db.models.functions import Length
CharField.register_lookup(Length)
Company.objects.order_by('name__length')

F表达式的一些理论

  • 在这里,我们拉出了reporter的值。stories_field从数据库进入内存,使用熟悉的Python操作符对其进行操作,然后将对象保存回数据库。男人装杂志 新增一篇新闻报道
reporter = Reporters.objects.get(name='男人装')
reporter.stories_filed += 1
reporter.save()
  • 通过reporter.stories_filed = F(‘stories_filed’) + 1看起来像一个普通的Python赋值给实例属性,实际上它是一个描述数据库操作的SQL构造。
  • 当Django遇到F()的实例时,它会覆盖标准Python操作符来创建一个封装的SQL表达式;在本例中,它指示数据库增加reporter. stories_field所表示的数据库字段。
  • 不管reporter.stories_filed的值是什么。 Python永远不会知道它是完全由数据库处理。Python通过Django的F()类所做的一切就是创建SQL语法来引用字段并描述操作。
from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
  • 要访问以这种方式保存的新值,对象必须重新加载
# 一般写法
reporter = Reporters.objects.get(pk=reporter.pk)
# 更简洁的方式 更简洁
reporter.refresh_from_db()
  • 除了在上面的单个实例上的操作中使用外,还可以在对象实例的查询集上使用F(),并使用update()。这将我们在上面使用的两个查询——get()和save()——减少为一个
reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)
  • 我们还可以使用update()来增加多个对象的字段值——这比将它们从数据库中全部放入Python、遍历它们、增加每个对象的字段值并将每个对象保存回数据库要快得多
Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JaysenLeo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值