單表查詢之神奇的雙下劃線
![](http://static.javashuo.com/static/loading.gif)
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:查詢各個做者出的書的總價格
![](http://static.javashuo.com/static/loading.gif)
>>> 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來表示分組後想要查找的字段值