Django查询

查询集

如果查的是一批数据,那么返回的是一个结果的集合

  • 他是django.db.models.query.QuerySet的实例
  • 他是可迭代对象

1、惰性求值

创建查询集不会带来任何对数据库的访问,直到调用方法使用数据时,才会访问数据库。

在迭代、序列化、if语句、切片、len()、repr()、bool()中都会立即求值

参考:

 https://docs.djangoproject.com/en/3.2/ref/models/querysets/#when-querysets-are-evaluated

2、缓存

参考 https://docs.djangoproject.com/en/3.2/topics/db/queries/#caching-and-querysets

每一个查询集都包含一个缓存,来最小化对数据库的访问。

新建查询集,缓存为空。首次对查询集求值时,会发生数据库查询,Django会把查询的结果存在这个缓存中,并返回请求的结果,接下来对查询集求值将使用缓存的结果。

通过日志,观察下面的2个例子是要真正生成的语句了。

from employee.models import Employee
emps = Employee.objects.all() # 结果集,本句不发起查询
print(type(emps)) # QuerySet查询集
print(1, emps)
print(2, emps)
print(3, emps[0])
print(4, emps[0])
print(emps._result_cache) # None
# 上面需要查询4次数据库
#输出
1 Employee object (10001)
2 Employee object (10001)
3 <QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
4 <QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
None
from employee.models import Employee
emps = Employee.objects.all() # 结果集,本句不发起查询
print(type(emps)) # QuerySet查询集
print(list(emps)) # print(*emps) 先遍历一遍,缓存住
print(1, emps)
print(2, emps)
print(3, emps[0])
print(4, emps[:])
print(emps._result_cache) # 结果集列表
#输出
1 Employee object (10001)
2 Employee object (10001)
3 <QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
4 <QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
[<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]

限制查询集(切片)

分页功能实现,使用限制查询集。

查询集对象可以直接使用索引下标的方式(不支持负索引),相当于SQL语句中的limit和offset子句。

注意:使用切片返回的新的结果集,依然是惰性求值,不会立即查询。但是使用了切片步长,会立即查询

qs = Employee.objects.all()[10:15]
# LIMIT 5 OFFSET 10
qs = Employee.objects.all()[20:30]
# LIMIT 10 OFFSET 20

注意:在使用print函数打印结果集的时候,看到SQL语句又自动添加的LIMIT21,这是怕打印的太长了。使用for循环迭代就没了。

结果集方法
名称 返回值类型 说明
all() QuerySet
filter() QuerySet 过滤,返回满足条件的数据
exclude() QuerySet 排除,排除满足条件的数据
order_by() QuerySet 排序,注意参数是字符串
values() QuerySet 返回集合内的元素是字典,字典内是字段和值得键值对

返回值如果是QuerySet 类型,可以链式调用

filter(k1=v1).filter(k2=k2) 等价于filter(k1=v1,k2=v2)

filter(pk=10)这里pk指的就是主键,不用关心主键字段名,当然也可以使用主键名filter(emp_no=10)

from django.core.wsgi import get_wsgi_application
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'solery.settings')
django.setup(set_prefix=False)

from employee.models import Employee

mgr = Employee.objects
print(mgr.all())
print(mgr.filter(pk=10001))
print(mgr.values())
print(mgr.exclude(emp_no=10010).order_by('-pk').values())
#输出
<QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10003 Bamford Parto>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10008 Kalloufi Saniya>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
<QuerySet [<E 10001 Facello Georgi>]>
<QuerySet [{'emp_no': 10001, 'birth_date': datetime.date(1953, 9, 2), 'first_name': 'Georgi', 'last_name': 'Facello', 'gender': 1, 'hire_date': datetime.date(1986, 6, 26)}, {'emp_no': 10002, 'birth_date': datetime.date(1964, 6, 2), 'first_name': 'Bezalel', 'last_name': 'Simmel', 'gender': 2, 'hire_date': datetime.date(1985, 11, 21)}, {'emp_no': 10003, 'birth_date': datetime.date(1959, 12, 3), 'first_name': 'Parto', 'last_name': 'Bamford', 'gender': 1, 'hire_date': datetime.date(1986, 8, 28)}, {'emp_no': 10004, 'birth_date': datetime.date(1954, 5, 1), 'first_name': 'Chirstian', 'last_name': 'Koblick', 'gender': 1, 'hire_date': datetime.date(1986, 12, 1)}, {'emp_no': 10005, 'birth_date': datetime.date(1955, 1, 21), 'first_name': 'Kyoichi', 'last_name': 'Maliniak', 'gender': 1, 'hire_date': datetime.date(1989, 9, 12)}, {'emp_no': 10006, 'birth_date': datetime.date(1953, 4, 20), 'first_name': 'Anneke', 'last_name': 'Preusig', 'gender': 2, 'hire_date': datetime.date(1989, 6, 2)}, {'emp_no': 10007, 'birth_date': datetime.date(1957, 5, 23), 'first_name': 'Tzvetan', 'last_name': 'Zielinski', 'gender': 2, 'hire_date': datetime.date(1989, 2, 10)}, {'emp_no': 10008, 'birth_date': datetime.date(1958, 2, 19), 'first_name': 'Saniya', 'last_name': 'Kalloufi', 'gender': 1, 'hire_date': datetime.date(1994, 9, 15)}, {'emp_no': 10009, 'birth_date': datetime.date(1952, 4, 19), 'first_name': 'Sumant', 'last_name': 'Peac', 'gender': 2, 'hire_date': datetime.date(1985, 2, 18)}, {'emp_no': 10010, 'birth_date': datetime.date(1963, 6, 1), 'first_name': 'Duangkaew', 'last_name': 'Piveteau', 'gender': 2, 'hire_date': datetime.date(1989, 8, 24)}, {'emp_no': 10011, 'birth_date': datetime.date(1953, 11, 7), 'first_name': 'Mary', 'last_name': 'Sluis', 'gender': 2, 'hire_date': datetime.date(1990, 1, 22)}, {'emp_no': 10012, 'birth_date': datetime.date(1960, 10, 4), 'first_name': 'Patricio', 'last_name': 'Bridgland', 'gender': 1, 'hire_date': datetime.date(1992, 12, 18)}, {'emp_no': 10013, 'birth_date': datetime.date(1963, 6, 7), 'first_name': 'Eberhardt', 'last_name': 'Terkki', 'gender': 1, 'hire_date': datetime.date(1985, 10, 20)}, {'emp_no': 10014, 'birth_date': datetime.date(1956, 2, 12), 'first_name': 'Berni', 'last_name': 'Genin', 'gender': 1, 'hire_date': datetime.date(1987, 3, 11)}, {'emp_no': 10015, 'birth_date': datetime.date(1959, 8, 19), 'first_name': 'Guoxiang', 'last_name': 'Nooteboom', 'gender': 1, 'hire_date': datetime.date(1987, 7, 2)}, {'emp_no': 10016, 'birth_date': datetime.date(1961, 5, 2), 'first_name': 'Kazuhito', 'last_name': 'Cappelletti', 'gender': 1, 'hire_date': datetime.date(1995, 1, 27)}, {'emp_no': 10017, 'birth_date': datetime.date(1958, 7, 6), 'first_name': 'Cristinel', 'last_name': 'Bouloucos', 'gender': 2, 'hire_date': datetime.date(1993, 8, 3)}, {'emp_no': 10018, 'birth_date': datetime.date(1954, 6, 19), 'first_name': 'Kazuhide', 'last_name': 'Peha', 'gender': 2, 'hire_date': datetime.date(1987, 4, 3)}, {'emp_no': 10019, 'birth_date': datetime.date(1953, 1, 23), 'first_name': 'Lillian', 'last_name': 'Haddadi', 'gender': 1, 'hire_date': datetime.date(1999, 4, 30)}, {'emp_no': 10020, 'birth_date': datetime.date(1952, 12, 24), 'first_name': 'Mayuko', 'last_name': 'Warwick', 'gender': 1, 'hire_date': datetime.date(1991, 1, 26)}]>
<QuerySet [{'emp_no': 10020, 'birth_date': datetime.date(1952, 12, 24), 'first_name': 'Mayuko', 'last_name': 'Warwick', 'gender': 1, 'hire_date': datetime.date(1991, 1, 26)}, {'emp_no': 10019, 'birth_date': datetime.date(1953, 1, 23), 'first_name': 'Lillian', 'last_name': 'Haddadi', 'gender': 1, 'hire_date': datetime.date(1999, 4, 30)}, {'emp_no': 10018, 'birth_date': datetime.date(1954, 6, 19), 'first_name': 'Kazuhide', 'last_name': 'Peha', 'gender': 2, 'hire_date': datetime.date(1987, 4, 3)}, {'emp_no': 10017, 'birth_date': datetime.date(1958, 7, 6), 'first_name': 'Cristinel', 'last_name': 'Bouloucos', 'gender': 2, 'hire_date': datetime.date(1993, 8, 3)}, {'emp_no': 10016, 'birth_date': datetime.date(1961, 5, 2), 'first_name': 'Kazuhito', 'last_name': 'Cappelletti', 'gender': 1, 'hire_date': datetime.date(1995, 1, 27)}, {'emp_no': 10015, 'birth_date': datetime.date(1959, 8, 19), 'first_name': 'Guoxiang', 'last_name': 'Nooteboom', 'gender': 1, 'hire_date': datetime.date(1987, 7, 2)}, {'emp_no': 10014, 'birth_date': datetime.date(1956, 2, 12), 'first_name': 'Berni', 'last_name': 'Genin', 'gender': 1, 'hire_date': datetime.date(1987, 3, 11)}, {'emp_no': 10013, 'birth_date': datetime.date(1963, 6, 7), 'first_name': 'Eberhardt', 'last_name': 'Terkki', 'gender': 1, 'hire_date': datetime.date(1985, 10, 20)}, {'emp_no': 10012, 'birth_date': datetime.date(1960, 10, 4), 'first_name': 'Patricio', 'last_name': 'Bridgland', 'gender': 1, 'hire_date': datetime.date(1992, 12, 18)}, {'emp_no': 10011, 'birth_date': datetime.date(1953, 11, 7), 'first_name': 'Mary', 'last_name': 'Sluis', 'gender': 2, 'hire_date': datetime.date(1990, 1, 22)}, {'emp_no': 10009, 'birth_date': datetime.date(1952, 4, 19), 'first_name': 'Sumant', 'last_name': 'Peac', 'gender': 2, 'hire_date': datetime.date(1985, 2, 18)}, {'emp_no': 10008, 'birth_date': datetime.date(1958, 2, 19), 'first_name': 'Saniya', 'last_name': 'Kalloufi', 'gender': 1, 'hire_date': datetime.date(1994, 9, 15)}, {'emp_no': 10007, 'birth_date': datetime.date(1957, 5, 23), 'first_name': 'Tzvetan', 'last_name': 'Zielinski', 'gender': 2, 'hire_date': datetime.date(1989, 2, 10)}, {'emp_no': 10006, 'birth_date': datetime.date(1953, 4, 20), 'first_name': 'Anneke', 'last_name': 'Preusig', 'gender': 2, 'hire_date': datetime.date(1989, 6, 2)}, {'emp_no': 10005, 'birth_date': datetime.date(1955, 1, 21), 'first_name': 'Kyoichi', 'last_name': 'Maliniak', 'gender': 1, 'hire_date': datetime.date(1989, 9, 12)}, {'emp_no': 10004, 'birth_date': datetime.date(1954, 5, 1), 'first_name': 'Chirstian', 'last_name': 'Koblick', 'gender': 1, 'hire_date': datetime.date(1986, 12, 1)}, {'emp_no': 10003, 'birth_date': datetime.date(1959, 12, 3), 'first_name': 'Parto', 'last_name': 'Bamford', 'gender': 1, 'hire_date': datetime.date(1986, 8, 28)}, {'emp_no': 10002, 'birth_date': datetime.date(1964, 6, 2), 'first_name': 'Bezalel', 'last_name': 'Simmel', 'gender': 2, 'hire_date': datetime.date(1985, 11, 21)}, {'emp_no': 10001, 'birth_date': datetime.date(1953, 9, 2), 'first_name': 'Georgi', 'last_name': 'Facello', 'gender': 1, 'hire_date': datetime.date(1986, 6, 26)}]>
(0.000) 
                SELECT VERSION(),
                       @@sql_mode,
                       @@default_storage_engine,
                       @@sql_auto_is_null,
                       @@lower_case_table_names,
                       CONVERT_TZ('2001-01-01 01:00:00', 'UTC', 'UTC') IS NOT NULL
            ; args=None; alias=default
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None; alias=default
(0.000) SELECT `employees`.`emp_no`, `employees`.`birth_date`, `employees`.`first_name`, `employees`.`last_name`, `employees`.`gender`, `employees`.`hire_date` FROM `employees` LIMIT 21; args=(); alias=default
(0.000) SELECT `employees`.`emp_no`, `employees`.`birth_date`, `employees`.`first_name`, `employees`.`last_name`, `employees`.`gender`, `employees`.`hire_date` FROM `employees` WHERE `employees`.`emp_no` = 10001 LIMIT 21; args=(10001,); alias=default
(0.000) SELECT `employees`.`emp_no`, `employees`.`birth_date`, `employees`.`first_name`, `employees`.`last_name`, `employees`.`gender`, `employees`.`hire_date` FROM `employees` LIMIT 21; args=(); alias=default
(0.000) SELECT `employees`.`emp_no`, `employees`.`birth_date`, `employees`.`first_name`, `employees`.`last_name`, `employees`.`gender`, `employees`.`hire_date` FROM `employees` WHERE NOT (`employees`.`emp_no` = 10010) ORDER BY `employees`.`emp_no` DESC LIMIT 21; args=(10010,); alias=default

返回单个值的方法

名称 说明
get() 严格返回满足条件的单个对象
count() 返回当前查询的总条数
first() 返回第一个对象
last() 返回最后一个对象
exist() 判断查询集中是否有数据,如果有则返回True
mgr = Employee.objects
# print(mgr.all())
# print(mgr.filter(pk=10001))
# print(mgr.values())
# print(mgr.exclude(emp_no=10010).order_by('-pk').values())
print(mgr.filter(pk=10010).get())
print(mgr.get(pk=10011))
# print(mgr.exclude(pk=10010).get()) #报错,因为get严格要求一个,返回的是employee对象
print(mgr.first())
print(mgr.last())
print(mgr.filter(pk=10001,gender=1).first())
print(mgr.count())
print(mgr.exclude(pk=10010).count())
#输出
Employee object (10010)
Employee object (10011)
Employee object (10001)
Employee object (10020)
Employee object (10001)
20
19

字段查询(Field Lookup) 表达式

参考 https://docs.djangoproject.com/en/3.2/ref/models/querysets/#field-lookups

字段查询表达式可以作为filter()、exclude()、get()的参数,实现where子句

语法:属性名称__比较运算符=值。注意:属性名和运算符之间使用双下划线

名称 举例 说明
exact filter(isdeleted=False)
filter(isdeleted__exact=False)
严格等于,可省略不写
contains exclude(title__contains=’天’) 是否包含,大小写敏感,等价于like binary ‘%天%’,模糊匹配效率很低
startswith
endswith
filter(title__startswith=’天’) 以什么开头或结尾,大小写敏感
isnull
isnotnull
filter(title__isnull=False) 是否为空
iexact
icontains
istartswith
iendswith
i的意思是忽略大小写
in filter(pk__in=[1,2,3,100]) 是否在指定范围数据中
gt、gte
lt、lte
filter(id__gt=3)
filter(id__lte=6)
filter(pub_date__gt=date(2000,1,1))
大于、小于等于
year
month
day
week_day
hour
minute
second
filter(pub_date__year=2000) 对日期类型属性处理
print(mgr.filter(first_name__contains='P'))
print(mgr.filter(last_name__startswith='P'))
print(mgr.filter(pk__gt=10010))
#输出
<QuerySet [<E 10003 Bamford Parto>, <E 10012 Bridgland Patricio>]>
<QuerySet [<E 10006 Preusig Anneke>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10018 Peha Kazuhide>]>
<QuerySet [<E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>

Q对象

虽然Django提供传入条件的方式,但是不方便,它还提供了Q对象来解决。

Q对象是django.db.models.Q,可以使用&、|操作符来组成逻辑表达式。~表示not。

print(mgr.filter(Q(pk__gt=10006) & Q(pk__lt=10008)))  #emp_no大于6且小于8
print(mgr.filter(pk__gt=10006).filter(pk__lt=10008))
print(mgr.filter(pk__gt=10006,pk__lt=10008))
print(mgr.filter(Q(pk__gt=10006),Q(pk__lt=10008)))
print(mgr.filter(pk__gt=10006) & mgr.filter(pk__lt=10008))

print(mgr.filter(pk__in=[10003,10008]))
print(mgr.filter(Q(pk=10003) | Q(pk=10008)))
print(mgr.filter(pk=10003) | mgr.filter(pk=10008))
print(mgr.filter(~Q(pk=10003) & ~Q(pk=10008)))
#输出
<QuerySet [<E 10007 Zielinski Tzvetan>]>
<QuerySet [<E 10007 Zielinski Tzvetan>]>
<QuerySet [<E 10007 Zielinski Tzvetan>]>
<QuerySet [<E 10007 Zielinski Tzvetan>]>
<QuerySet [<E 10007 Zielinski Tzvetan>]>
<QuerySet [<E 10003 Bamford Parto>, <E 10008 Kalloufi Saniya>]>
<QuerySet [<E 10003 Bamford Parto>, <E 10008 Kalloufi Saniya>]>
<QuerySet [<E 10003 Bamford Parto>, <E 10008 Kalloufi Saniya>]>
<QuerySet [<E 10001 Facello Georgi>, <E 10002 Simmel Bezalel>, <E 10004 Koblick Chirstian>, <E 10005 Maliniak Kyoichi>, <E 10006 Preusig Anneke>, <E 10007 Zielinski Tzvetan>, <E 10009 Peac Sumant>, <E 10010 Piveteau Duangkaew>, <E 10011 Sluis Mary>, <E 10012 Bridgland Patricio>, <E 10013 Terkki Eberhardt>, <E 10014 Genin Berni>, <E 10015 Nooteboom Guoxiang>, <E 10016 Cappelletti Kazuhito>, <E 10017 Bouloucos Cristinel>, <E 10018 Peha Kazuhide>, <E 10019 Haddadi Lillian>, <E 10020 Warwick Mayuko>]>
(0.000) 

可使用&|和Q对象来构造复杂的逻辑表达式,可以使用一个或多个Q对象。

如果混用关键字参数和Q对象,那么Q对象必须位于关键字参数的前面

聚合、分组

aggregate()返回字典,方便使用

print(mgr.filter(pk__gt=10010).count())#单值
print(mgr.filter(pk__gt=10010).aggregate(Count('pk'),Max('pk'))) #字典
print(mgr.filter(pk__lte=10010).aggregate(Avg('pk')))
print(mgr.aggregate(Max('pk'),min=Min('pk'))) #别名

annotate()方法用来分组聚合,返回查询集

print(mgr.filter(pk__gt=10010).aggregate(Count('pk'))) #字典
x = mgr.filter(pk__gt=10010).annotate(countS=Count('pk'))  #返回查询集,没指定分组字段
#使用主键分组
for n in x:
    print(n)
    print(n.__dict__)#里面多了个countS别名属性
print(mgr.filter(pk__gt=10010).values('emp_no').annotate(Count('pk')))

values方法,放在annotate前面就是指定分组字段,之后就是取结果中的字段

s = mgr.filter(pk__gt=10010).values('gender').annotate(Count('pk'))
for n in s:
    print(s)
#输出
<QuerySet [{'gender': 2, 'pk__count': 3}, {'gender': 1, 'pk__count': 7}]>
mgr = Employee.objects
s = mgr.filter(pk__gt=10010).values('gender').annotate(c=Count('pk')).order_by('-c') # 查询集
print(s)
for x in s:
    print(x) # 字典
# 运行结果如下
<QuerySet [{'gender': 1, 'c': 7}, {'gender': 2, 'c': 3}]> {'gender': 1, 'c': 7} {'gender': 2, 'c': 3}
mgr = Employee.objects
s = mgr.filter(pk__gt=10010).values('gender').annotate(
    Avg('pk'), c=Count('pk')
).order_by('-c').values('pk__avg', 'c') # 查询集,但后面的values过滤了每个对象字典的key
print(s)
for x in s:
    print(x) # 字典
# 运行结果如下
<QuerySet [{'pk__avg': 10015.5714, 'c': 7}, {'pk__avg': 10015.3333, 'c': 
3}]> {'pk__avg': 10015.5714, 'c': 7} {'pk__avg': 10015.3333, 'c': 3}