单表查询之神奇的双下划线

models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于十一、22、33的数据 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 相似的还有:startswith,istartswith, endswith, iendswith date字段还能够: models.Class.objects.filter(first_day__year=2017) date字段能够经过在其后加__year,__month,__day等来获取date的特色部分数据 # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) 须要注意的是在表示一年的时间的时候,咱们一般用52周来表示,由于天数是不肯定的,老外就是按周来计算薪资的哦~
ForeignKey操做
正向查找(两种方式)
1.对象查找(跨表)
语法:
对象.关联字段.字段
要点:先拿到对象,再经过对象去查对应的外键字段,分两步
示例:
book_obj = models.Book.objects.first() # 第一本书对象(第一步)
print(book_obj.publisher) # 获得这本书关联的出版社对象
print(book_obj.publisher.name) # 获得出版社对象的名称
2.字段查找(跨表)
语法:
关联字段__字段
要点:利用Django给咱们提供的神奇的双下划线查找方式
示例:
models.Book.objects.all().values("publisher__name") #拿到全部数据对应的出版社的名字,神奇的下划线帮咱们夸表查询
反向操做(两种方式)
1.对象查找
语法:
obj.表名_set
要点:先拿到外键关联多对一,一中的某个对象,因为外键字段设置在多的一方,因此这里仍是借用Django提供的双下划线来查找
示例:
publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象 books = publisher_obj.book_set.all() # 找到第一个出版社出版的全部书 titles = books.values_list("title") # 找到第一个出版社出版的全部书的书名
结论:若是想经过一的那一方去查找多的一方,因为外键字段不在一这一方,因此用__set来查找便可
2.字段查找
语法:
表名__字段
要点:直接利用双下滑线完成夸表操做
titles = models.Publisher.objects.values("book__title")
ManyToManyField
class RelatedManager
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种状况:
- 外键关系的反向查询
- 多对多关联关系
简单来讲就是在多对多表关系而且这一张多对多的关系表是有Django自动帮你建的状况下,下面的方法才可以使用。
方法
create()
建立一个关联对象,并自动写入数据库,且在第三张双方的关联表中自动新建上双方对应关系。
models.Author.objects.first().book_set.create(title="偷塔秘籍") 上面这一句干了哪些事儿: 1.由做者表中的一个对象跨到书籍比表 2.新增名为偷塔秘籍的书籍并保存 3.到做者与书籍的第三张表中新增二者之间的多对多关系并保存
add()
把指定的model对象添加到第三张关联表中。
添加对象
>>> author_objs = models.Author.objects.filter(id__lt=3) >>> models.Book.objects.first().authors.add(*author_objs)
添加id
>>> models.Book.objects.first().authors.add(*[1, 2])
set()
更新某个对象在第三张表中的关联对象。不一样于上面的add是添加,set至关于重置
>>> book_obj = models.Book.objects.first() >>> book_obj.authors.set([2, 3])
remove()
从关联对象集中移除执行的model对象(移除对象在第三张表中与某个关联对象的关系)
>>> book_obj = models.Book.objects.first() >>> book_obj.authors.remove(3)
clear()
从关联对象集中移除一切对象。(移除全部与对象相关的关系信息)
>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.clear()
注意:
对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
举个例子:
ForeignKey字段没设置null=True时,
class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to=Publisher)
没有clear()和remove()方法:
>>> models.Publisher.objects.first().book_set.clear() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'RelatedManager' object has no attribute 'clear'
当ForeignKey字段设置null=True时,
class Book(models.Model): name = models.CharField(max_length=32) publisher = models.ForeignKey(to=Class, null=True)
此时就有clear()和remove()方法:
>>> models.Publisher.objects.first().book_set.clear()
再次强调:
- 对于全部类型的关联字段,add()、create()、remove()和clear(),set()都会立刻更新数据库。换句话说,在关联的任何一端,都不须要再调用save()方法。
聚合查询和分组查询
聚合(利用聚合函数)
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。
键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
用到的内置函数:
from django.db.models import Avg, Sum, Max, Min, Count
示例:
>>> from django.db.models import Avg, Sum, Max, Min, Count >>> models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333}
若是你想要为聚合值指定一个名称,能够向聚合子句提供它。
>>> models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333}
若是你但愿生成不止一个聚合,你能够向aggregate()子句中添加另外一个参数。因此,若是你也想知道全部图书价格的最大值和最小值,能够这样查询:
>>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
分组
咱们在这里先复习一下SQL语句的分组。
假设如今有一张公司职员表:
咱们使用原生SQL语句,按照部分分组求平均工资:
select dept,AVG(salary) from employee group by dept;
ORM查询:
from django.db.models import Avg Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg") 这里须要注意的是annotate分组依据就是他前面的值, 若是前面没有特色的字段,则默认按照ID分组, 这里有dept字段,因此按照dept字段分组
连表查询的分组:
SQL查询:
select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;
ORM查询:
from django.db.models import Avg models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")
更多示例:
示例1:统计每一本书的做者个数
>>> book_list = models.Book.objects.all().annotate(author_num=Count("author")) >>> for obj in book_list: ... print(obj.author_num) ... 1
示例2:统计出每一个出版社买的最便宜的书的价格
>>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price")) >>> for obj in publisher_list: ... print(obj.min_price) ... 9.90 19.90
方法二:
>>> models.Book.objects.values("publisher__name").annotate(min_price=Min("price")) <QuerySet [{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')}, {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}]>
示例3:统计不止一个做者的图书
>>> models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1) <QuerySet [<Book: 番茄物语>]>
示例4:根据一本图书做者数量的多少对查询集 QuerySet进行排序
>>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num") <QuerySet [<Book: 香蕉物语>, <Book: 橘子物语>, <Book: 番茄物语>]>
示例5:查询各个做者出的书的总价格

>>> models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price") <QuerySet [{'name': '小精灵', 'sum_price': Decimal('9.90')}, {'name': '小仙女', 'sum_price': Decimal('29.80')}, {'name': '小魔女', 'sum_price': Decimal('9.90')}]>
总结
value里面的参数对应的是sql语句中的select要查找显示的字段,
filter里面的参数至关于where或者having里面的筛选条件
annotate自己表示group by的做用,前面找寻分组依据,内部放置显示可能用到的聚合运算式,后面跟filter来增长限制条件,最后的value来表示分组后想要查找的字段值