草庐IT

Django 聚合分组F与Q查询及choices

Linux huaxiayuyi 2023-04-19 原文

一、聚合查询


需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg

关键语法:aggregate(聚合结果别名 = 聚合函数(参数))

查询结果:使用聚合函数,从每一个组中获取结果:字典

注意点:

1 聚合函数必须在分组之后才能使用

2 没有分组,即默认整体就是一组

3 查询结果为 普通字典

"""
    聚合查询通常情况下都是配合分组一起使用的
    只要是跟数据库相关的模块 
      基本上都在 django.db.models 里面
      上述没有那么应该在 django.db里面
"""
from django.db.models import Max, Min, Sum, Count, Avg
# 1 所有书的平均价格
res = models.Book.objects.aggregate(Avg('price'))
print(res)
# 2 上述方法一次性使用
res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Count('pk'), Avg('price'))
print(res)

 

二、分组查询


1 关键字:annotate

2 默认以当前表 id 分组,并使用聚合函数在组内进行聚合计算,得到结果作为查询结果中组内的属性

from django.db.models import Max, Min, Sum, Count, Avg
# 1 统计每一本书的作者个数
res = models.Book.objects.annotate()  # models后面点什么 就是按什么分组
res1 = models.Book.objects.annotate(author_num = Count('authors')).values('title', 'author_num')
res2 = models.Book.objects.annotate(author_num = Count('authors__nid')).values('title', 'author_num')
print(res, res1, res3)
"""
author_num 自己定义的字段 用来存储统计出来的每本书对应的作者个数
"""

# 2 统计每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price = Min('book__price')).values('name', 'min_price')
print(res)

# 3 统计不止一个作者的图书
#     先按照图书分组 求每一本书对应的作者个数
#     过滤出不止一个作者的图书
res = models.Book.objects.annotate(author_num = Count('authors')).filter(author_num__gt = 1).values('title', 'author_num')
print(res)

# 4 查询每个作者出的书的总价格
res = models.Author.objects.annotate(sum_price = Sum('book__price')).values('name', 'sum_price')
print(res)

# 5 统计 price大于150元 的书籍的作者个数
res = models.Book.objects.filter(price__gt = 150).annotate(num_authors = Count('authors')).values('title', 'num_authors')
print(res)

 

 

三、F与Q查询


 

# F查询
"""
能够帮助你直接获取到表中某个字段对应的数据
"""
from django.db.models import F

# 1 将所有书籍的价格提升 10 块
models.Book.objects.update(price = F('price') + 10)


# 2 将 django 书的名称后面加上 ' web' 字
"""
在操作字符类型的数据的时候 F不能够直接做到字符串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.filter(title = "django").update(title = Concat(F('title'), Value(' web')))

 

# Q查询
"""
filter括号内多个参数是and关系
"""
from django.db.models import Q

# Q包裹逗号分割 还是and关系
res1 = models.Book.objects.filter(Q(price__lt = 300), Q(price__gt = 400))  
print(res1)

# | or关系
res2 = models.Book.objects.filter(Q(pub_date__lt = '2020-01-01') | Q(price__gt = 300)) 
print(res2)

# ~ not关系
res3 = models.Book.objects.filter( ~ Q(pub_date__lt = '2020-01-01') | Q(price__lt = 200)) 
print(res3)  # <QuerySet []>

# Q的高阶用法  能够将查询条件的左边也变成字符串的形式
# 提前生成 Q 对象,并使用 append方法 添加条件
q = Q()
q.connector = 'or'
q.children.append(('pub_date__lt', '2020-01-01'))
q.children.append(('price__lt', 200))
res = models.Book.objects.filter(q)  # 默认是and关系
print(res)

 

四、特殊参数choices


1 定义字段时,指定参数 choices

2 choices 的值为元组套元组(事先定义好,一般在该表类中定义该字段之前定义)

3 每一个元组存放两个元素,形成一种对应关系

4 往数据库中存值时,该字段的值存为元组第一个元素即可

5 通过 对象.get_字段名_display() 获取对应的元组第二个元素值,当没有对应关系时,返回的是它本身

示例:

# 定义一个 UserTest 表
class UserTest(models.Model):
    name = models.CharField(max_length = 64)
    gender_choices = ((1, '男'),(2, '女'),(3, '其他'))
    gender = models.IntegerField(choices = gender_choices)
    
# 同步迁移到数据库
python manage.py makemigrations
python manage.py migrate

# 在 test.py 配置测试环境
# 录入数据
models.UserTest.objects.create(name = '小微', gender = 1)
models.UserTest.objects.create(name = '小芬', gender = 2)
models.UserTest.objects.create(name = '小桃', gender = 3)
models.UserTest.objects.create(name = '小月', gender = 4)

# 验证choices
for user_obj in models.UserTest.objects.all():
    print(user_obj.gender, end=' ')
    print(user_obj.get_gender_display())
'''
1 男
2 女
3 其他
4 4
'''

 

有关Django 聚合分组F与Q查询及choices的更多相关文章

  1. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  4. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  5. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  6. ruby-on-rails - solr 清理查询 - 2

    我在Rails上使用带有ruby​​的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s

  7. ruby-on-rails - Rails 3 在一个查询中包含多个表 - 2

    我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params

  8. ruby-on-rails - Sunspot:如何对具有不同值的多个字段进行全文查询? - 2

    我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使

  9. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  10. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

    我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

随机推荐