/ORM操做13條基礎-單表查詢-外鍵-多對多-聚合和分組查詢-F-Q-事物html
day74 1. 內容回顧 1. ORM 1. 13條 1. 返回queryset的 all() filter() exclude() order_by() reverse() distinct() values() values_list() 2. 返回對象的 get() first() last() 3. 返回布爾值 exists() 4. 返回數字 count() 2. django使用mysql數據庫的步驟 1. 建立一個mysql數據庫 2. 配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'orm_homework', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': 3306, } } 3. 告訴django使用pymysql鏈接你的mysql數據庫(mysqldb) 在與settings同級目錄下的__init__.py中寫 import pymysql pymysql.install_as_MySQLdb() 4. 在APP下的models.py中寫類(繼承Model) 5. 執行數據庫遷移的命令 python manage.py makemigrations # 記錄models的變動記錄 python manage.py migrate # 將變動記錄同步到數據庫中 2. 週末做業 見代碼 3. OneToOneField(to='關聯的表') (一對一) 在ForeignKey基礎上加一個約束 unique=true 1. 全部的內容能夠寫在一個表中 2. 有的字段不常查,但有的字段查的很頻繁 4. 外鍵ForeignKey book_obj.publisher ——》 關聯的出版社對象 book_obj.publisher_id 反向查詢: 不指定related_name pub_obj.book_set ——》關係管理對象 指定related_name='books' pub_obj.books ——》關係管理對象 5. 多對多ManyToManyField book_obj.author 多對多的方法: create() add() remove() set() clear() 6. 單表的增刪改查 create delete update() .屬性 = '' save() 7. 進階 1. 聚合和分組 aggregate 終止子句 annotate 2. F 和 Q ~取反 & and | 或 3. 事務 2. 今日內容 0. 登陸的實例 1. cookie 1. cookie是什麼? cookie是保存在瀏覽器上一組組鍵值對 2. 特性: 1. 是服務器讓瀏覽器設置的。瀏覽器有權利不設置。 2. 訪問其餘頁面的時候攜帶着cookie。 2. 能幹什麼? 1. 作登陸 2. session 1. 保存在服務器上的鍵值對 2. 一個cookie對應一個session 流程: 1. 給首次登陸的用戶設置一個cookie session:asdasdasasdasdas 2. 開闢一塊空間存session 3. session中存要存的數據(鍵值對) 4. 返回給瀏覽器cookie # 設置session request.session['is_login'] = 'True' # 獲取session request.session.get('is_login', '')
https://www.cnblogs.com/maple-shaw/articles/9403501.htmlpython
https://www.cnblogs.com/maple-shaw/articles/9323320.htmlmysql
https://www.cnblogs.com/maple-shaw/articles/9414626.html -練習題git
# 查找全部書名裏包含金老闆的書 # ret=models.Book.objects.filter(title__icontains='金老闆').values_list('title') # print(ret) # 查找出版日期是2018年的書 # ret=models.Book.objects.filter(publisher_date__year=2018).values_list('title','publisher_date') # print(ret) # 查找出版日期是2017年的書名 # ret=models.Book.objects.filter(publisher_date__year=2017).values_list('title','publisher_date') # print(ret) # 查找價格大於10元的書 # ret=models.Book.objects.filter(price__gt=10).values_list('title') # print(ret) # 查找價格大於10元的書名和價格 # ret = models.Book.objects.filter(price__gt=10).values_list('title', 'price') # print(ret) # 查找memo字段是空的書 # ret=models.Book.objects.filter(memo__isnull=True) # print(ret) # 查找在北京的出版社 # ret=models.Publisher.objects.filter(city__icontains='北京').values_list('name','city') # print(ret) # 查找名字以沙河開頭的出版社 # ret = models.Publisher.objects.filter(name__startswith='沙河').values_list('name', 'city') # print(ret) ############----------------重點-------------------------#################### # 查找「沙河出版社」出版的全部書籍 # ret=models.Book.objects.filter(publisher__name='沙河出版社').values_list('publisher__name','title') # print(ret) # 查找每一個出版社出版價格最高的書籍價格 # ret=models.Publisher.objects.annotate(max=Max('books__price')).values_list('name','books__title','max') # print(ret) # ret=models.Book.objects.filter(publisher__name='沙河出版社') # print(ret) # ret=models.Publisher.objects.filter(books__title='跟金老闆學開車') # print(ret) # 查找每一個出版社的名字以及出的書籍數量 # ret=models.Publisher.objects.annotate(num=Count('books')).values_list('name','num') # print(ret) # 查找做者名字裏面帶「小」字的做者 # ret=models.Author.objects.filter(name__contains='小').values_list('name') # print(ret) # ret=models.Author.objects.all().values_list('name') # print(ret) # 查找年齡大於30歲的做者 # ret=models.Author.objects.filter(age__gt=30).values_list('name','age','authors__title') # print(ret) # 查找手機號是155開頭的做者 # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','phone') # print(ret) # ret=models.Author.objects.all().values_list('phone') # print(ret) # 查找手機號是155開頭的做者的姓名和年齡 # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','age') # print(ret) # 查找每一個做者寫的價格最高的書籍價格 # ret=models.Author.objects.annotate(max=Max('authors__price')).values_list('name','authors__price') # print(ret) # 查找每一個做者的姓名以及出的書籍數量 # ret=models.Author.objects.all().annotate(num=Count('authors')).values_list('name','num') # print(ret) # 查找書名是「跟金老闆學開車」的書的出版社 # book_obj=models.Book.objects.filter(title='跟金老闆學開車') # ret=book_obj.publisher # print(ret) # 查找書名是「跟金老闆學開車」的書的出版社所在的城市 # book_obj=models.Book.objects.get(title='跟金老闆學開車') # ret=book_obj.publisher.city # print(ret) # 查找書名是「跟金老闆學開車」的書的出版社的名稱 # book_obj=models.Book.objects.filter(title='跟金老闆學開車') # ret=book_obj.publisher.name # print(ret) # 查找書名是「跟金老闆學開車」的書的出版社出版的其餘書籍的名字和價格 # book_obj=models.Book.objects.get(title='跟金老闆學開車') # ret=book_obj.publisher.books.exclude(title='跟金老闆學開車').values_list('title','price') # print(ret) # ret=models.Publisher.objects.get(books__title='跟金老闆學開車').books.exclude(title='跟金老闆學開車').values_list('title','price') # print(ret) # obj=models.Publisher.objects.get(book__title='跟金老闆學開車').book_set.exclude(title='跟金老闆學開車').values_list('title','price') # ret=obj.book_set.all() # print(obj) # 查找書名是「跟金老闆學開車」的書的全部做者 # ret=models.Book.objects.get(title='跟金老闆學開車').author.all() # print(ret) # 查找書名是「跟金老闆學開車」的書的做者的年齡 # ret=models.Book.objects.get(title='跟金老闆學開車').author.all().values_list('age','name') # print(ret) # 查找書名是「跟金老闆學開車」的書的做者的手機號碼 # ret=models.Book.objects.get(title='跟金老闆學開車').author.all().values_list('phone','name') # print(ret) # 查找書名是「跟金老闆學開車」的書的做者們的姓名以及出版的全部書籍名稱和價錢 # book_obj = models.Book.objects.get(title='跟金老闆學開車') # ret=book_obj.author.all() # for aut in ret: # print(aut) # ret=aut.authors.all().values_list('title','price') # print(ret) # ret=models.Author.objects.filter(authors__title='跟金老闆學開車').values('name','authors__title','authors__price') # print(ret)
/ sql
/數據庫
/django
/瀏覽器
QuerySet
API referencehttps://docs.djangoproject.com/en/1.11/ref/models/querysets/服務器
/cookie
/
/
/
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
#上面的代碼,在manage.py文件裏也有,能夠考慮複製過來
#引入django import django django.setup()
#引入models
from app01 import models books = models.Book.objects.all() print(books)
1,在項目下建一個文件夾,而後建一個py文件,把上面代碼粘貼進去,
2,寫好語句後, 右鍵執行便可,不用在啓動django項目,直接看結果,
示例代碼:
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models ret = models.Person.objects.all() print(ret[0],'**',type(ret),'**',type(ret[0]))
輸出結果
ret=models.Person.objects.all() #類型是類,QuerySet對象 type(ret)---><class 'django.db.models.query.QuerySet'> ret[0] Person object type(ret[0]) <class 'app01.models.Person'>
/
/
order_by的默認排序, ordering=('id','age'),ID同樣,再按age進行排序,
class Person(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=32) age=models.IntegerField() birth=models.DateField() def __str__(self): return "<Person obj:{} {}>".format(self.id,self.name) # 加上這個以後,默認取出來就是已經排序的 class Meta: #後面要寫元組, ordering=('id')
下面再寫的取出來就是倒序了
ret=models.Person.objects.all().reverse()
也能夠這樣寫,
models.Person.objects.all().order_by('id').reverse()
具體演示代碼
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models # all 獲取全部對象 ——》 QuerySet ret = models.Person.objects.all() # get 獲取單獨的對象 ——》 對象 # 找不到或者找到多個就報錯 ret= models.Person.objects.get(id=1,name='阿旭') # filter 過濾 獲取全部知足條件的對象 ——》QuerySet ret = models.Person.objects.filter(id=1) # exclude 獲取不知足條件的全部對象 ret = models.Person.objects.exclude(id=1) # values ——》QuerySet 元素是字典 # 不寫參數 默認全部字段的名字和值 # 寫參數 拿到指定字段的名字和值 ret = models.Person.objects.all().values('id','name') ret = models.Person.objects.values('id','name') # values_list ——》QuerySet 元素是元組 只有值沒有字段名 # 不寫參數 默認全部字段值 # 寫參數 拿到指定字段值 ret = models.Person.objects.values_list('name','id') # print(ret) # for i in ret : # print(i,type(i)) # reverse 對已經排序的QuerySet進行反轉 ret = models.Person.objects.all().reverse() # distinct 去重 ——》QuerySet # count 對QuerySet中的元素進行計數 ret = models.Person.objects.filter(id=100).count() # first 取QuerySet中的第一個元素 ret = models.Person.objects.all().first() # last 取QuerySet中的最後一個元素 ret = models.Person.objects.all().last() ret = models.Person.objects.values_list().last() ret = models.Person.objects.filter(id=100).first() # exists 判斷查詢結果是否有值 ret = models.Person.objects.filter(id=100).exists() # print(ret) # order_by 按字段進行排序 ——》QuerySet ret =models.Person.objects.order_by('age') print(ret)
/
/
all(),
filter(),
exclude(),
order_by(), 裏面能夠放多個參數
reverse(),對已經排序的進行翻轉
distinct(),去重
values() 返回一個可迭代的字典序列,裏面能夠放參數,放了參數就是僅顯示參數的內容,
values_list() 返回一個可迭代的元祖序列, 也能夠放參數,
get(), 取不到或者取到多個會報錯
first(), 取不到是Null
last().
exists()
count()
id__lt,id__gt,id__in,id__range=[]是列表
name__contains='str'
name__icontains='str'
name__startswith='xx'
name__endswith='xx'
name__iendswith='xx'
birth__year
eq 就是 EQUAL等於
ne 就是 NOT EQUAL不等於
gt 就是 GREATER THAN大於
lt 就是 LESS THAN小於
gte 就是 GREATER THAN OR EQUAL 大於等於
lte 就是 LESS THAN OR EQUAL 小於等於
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models ret = models.Person.objects.all() #小於10的,less than ret=models.Person.objects.filter(id__lt=10) #大於1的,great than ret=models.Person.objects.filter(id__gt=3) #大於等於3的, ret=models.Person.objects.filter(id__gt=3) #大於3小於5的, ret=models.Person.objects.filter(id__gt=3,id__lt=5) #取反,拿出小於等於3的, ret=models.Person.objects.exclude(id__gt=3) #還能夠設置範圍,還能夠換成exclude ret=models.Person.objects.filter(id__in=[1,3,5]) #使用range,1和5都能取到, ret=models.Person.objects.filter(id__range=[1,5]) #查選包含特定字符的, ret=models.Person.objects.filter(name__contains='啊') #注意加了一個i,是不區分大小寫的意思, ret=models.Person.objects.filter(name__icontains='啊') #表示以哪一個字符爲開頭 ret=models.Person.objects.filter(name__startswith='阿') #以什麼結尾, ret=models.Person.objects.filter(name__endswith='阿') #加了一個i,不區分大小寫, ret=models.Person.objects.filter(name__iendswith='阿') #查找日期符合條件的, ret=models.Person.objects.filter(birth__year='2018') ret=models.Person.objects.filter(birth__month='09') ret=models.Person.objects.filter(birth__year='2018',birth__month='09') print(ret)
Django終端打印SQL語句
在Django項目的settings.py文件中在最後複製粘貼以下代碼:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
即爲你的Django項目配置上一個名爲django.db.backends的logger實例便可查看翻譯後的SQL語句。
/
/
外鍵設置在書籍,經過book查詢publisher,稱之爲正向查詢,反過來就是反向查詢,
#book_obj.publishr是直接拿到了publisher對象了,關聯的出版社對象, print(book_obj.publisher,type(book_obj.publisher)) 輸出:Publisher object <class 'app01.models.Publisher'>
#區分兩者的sql語句條數
print(book_obj.publisher_id)
print(book_obj.publisher.id)
語法:
對象.關聯字段.字段
book_obj = models.Book.objects.first() # 第一本書對象 print(book_obj.publisher) # 獲得這本書關聯的出版社對象 print(book_obj.publisher.name) # 獲得出版社對象的名稱
models.Book.objects.filter(publisher__name='新華出版社') #查出 出版社='新華出版社' 出版的全部書,
此處就是publisher查找book
/
語法:
拿到關聯對象
publisher_obj = models.Publisher.objects.first() # 找到第一個出版社對象
books = publisher_obj.book_set.all() # 找到第一個出版社出版的全部書
titles = books.values_list("title") # 找到第一個出版社出版的全部書的書名
示例代碼1
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings") import django django.setup() from app01 import models # 正向查詢 book ——》 publisher # 基於對象查詢 # book_obj = models.Book.objects.get(id=1) # print(book_obj.id) # print(book_obj.title) # print(book_obj.publisher_id) # print(book_obj.publisher_id) # 關聯的出版社對象 # print(book_obj.publisher.id) # 關聯的出版社對象 # print(book_obj.publisher.name) # 基於字段查詢 # ret= models.Book.objects.filter(publisher__name='沙河出版社') # ret= models.Book.objects.filter(publisher_id=1) # print(ret) # 反向查詢 publisher ——》 book # 基於對象的查詢 # 一 —— 》 多 表名小寫_set ——》 管理對象 .all() 出版社關聯的全部書籍對象 pub_obj = models.Publisher.objects.first() # 表名小寫_set # print(pub_obj) # ret = pub_obj.book_set.all() # print(pub_obj.book_set,type(pub_obj.book_set)) # print(ret) # 指定了related_name books # print(pub_obj.books.all()) # 基於字段的查詢 ret = models.Publisher.objects.filter(xx__title='跟太亮學開車') print(ret)
關於查找時,能夠簡化的寫法,
在models裏面須要對應設置,注意related_name的添加, 也是反向查詢用的,
class Book(models.Model): title=models.CharField(max_length=32) #下面一行是要關聯的外鍵 publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE)
ret=models.Publisher.objects.filter(books__title='這就是書名') #此處的books__title books是related_name
#若是下面圖片的related_query_name='xx',寫了,上面的books__title就要換成:xx__title,
與圖片的關係
pub_obj=models.Publisher.objects.first() pub_obj.books.create(title='跟老男孩學思想')
/
/
"關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器。
它存在於下面兩種狀況:
簡單來講就是當 點後面的對象 可能存在多個的時候就可使用如下的方法。
拿到管理對象,
author_obj=models.Author.objects.get(id=1) # books就是設置的那個多對多,books=models.ManyToManyField('Book') print(author_obj.books,type(author_obj.books)) #拿到管理對象, # 輸出:app01.Book.None <class 'django.db.models.fields.related_descriptors print(author_obj.books.all()) #拿到QuerySet #輸出:<QuerySet [<Book: <Person obj:5 跟太亮學開車>>, <Book: <Person obj:6 跟太白學燙頭>>]>
#create # 1,建立書籍對象(與出版社進行關聯) # 2,該對象和做者 author_obj = models.Author.objects.get(id=1)
此處的books就是以前的->books=models.ManyToManyField('Book')
author_obj.books.create(title='XX與嫂子的故事',publisher_id=1)
/
/
/
add()括號裏面能夠放一個或多個數據, 能夠放id,還能夠放對象,
#給做者添加書籍, author_obj = models.Author.objects.get(id=1) #能夠添加一個或多個,add() # author_obj.books.add(9) author_obj.books.add(5,6,8,9)
區分與set的不一樣
author_obj.books.set([1,6,8,9])
另外一種添加方式
author_obj=models.Author.objects.get(id=1) # 獲取指定id的書籍 books=models.Book.objects.filter(id__in=[1,6,8,9]) #須要打散才能進行傳參 author_obj.books.add(*books)
與add對比使用,add是添加的一個id,或者一個對象,
set能夠添加列表,或者queryset集合,
author_obj=models.Author.objects.get(id=1) books=models.Book.objects.filter(id__in=[1,6,8,9]) # 下面兩行的代碼是等價的, # author_obj.books.set([1,6,8,9]) author_obj.books.set(books)
/
/
author_obj=models.Author.objects.get(id=1) books=models.Book.objects.filter(id__in=[1,6,8,9]) # remove 能夠移除一個或多個 author_obj.books.remove(1) author_obj.books.remove(6,8,9) # 能夠移除對象 author_obj.books.remove(*books)
clear()
從關聯對象集中移除一切對象。
author_obj=models.Author.objects.get(id=1) #把跟這個做者關聯的書,都清空掉, author_obj.books.clear()
設置null=True
就是刪除出版社跟書的對應關係時,外鍵沒有了,往數據庫寫的時候,寫不進去,須要設置null=True才能寫進去,
在models裏設置Book類,而後執行兩條命令.
注意:
設置null=True
publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE,null=True)
設置null=True以後,示例代碼
pub_obj=models.Publisher.objects.get(id=1) #一對多的管理對象remove不能使用id,使用對象 # pub_obj.books.remove(models.Book.objects.get(id=5)) #清空這個出版社下全部關聯的書, pub_obj.books.clear()
/
/
models裏面,Book類添加包含小數的字段
price=models.DecimalField(max_digits=5,decimal_places=2)
1,aggregate的使用,觀察輸出結果,
ret=models.Book.objects.all().aggregate(Avg('price')) print(ret,type(ret)) # 輸出:{'price__avg': 50.0} <class 'dict'>
還能夠更名字
ret=models.Book.objects.all().aggregate(make_name=Avg('price'))
print(ret,type(ret))
# {'make_name': 50.0} <class 'dict'>
還能夠多放參數
ret=models.Book.objects.all().aggregate(Avg('price'),Max('price'))
2,能夠更名字,還能夠多放參數,
/
/
1,統計每本書的做者個數
# 統計每本書的做者個數 #.all能夠省略不寫, # ret=models.Book.objects.all().annotate(Count('author')) ret=models.Book.objects.annotate(Count('author')) for i in ret.values(): print(i)
輸出結果
'''輸出: {'id': 1, 'title': '宮保雞丁指南', 'publisher_id': 1, 'price': Decimal('10.00'), 'author__count': 1} {'id': 2, 'title': '包子真貴', 'publisher_id': 4, 'price': Decimal('20.00'), 'author__count': 1} {'id': 3, 'title': '陶馨園真便宜', 'publisher_id': 5, 'price': Decimal('30.00'), 'author__count': 1} {'id': 4, 'title': '護國寺豆汁真騷', 'publisher_id': 3, 'price': Decimal('40.00'), 'author__count': 0} {'id': 5, 'title': '跟太亮學開車', 'publisher_id': 1, 'price': Decimal('50.00'), 'author__count': 1} {'id': 6, 'title': '跟太白學燙頭', 'publisher_id': 1, 'price': Decimal('60.00'), 'author__count': 1} {'id': 7, 'title': '新華字典', 'publisher_id': 2, 'price': Decimal('70.00'), 'author__count': 1} {'id': 8, 'title': '戴綠與嫂子的故事', 'publisher_id': 1, 'price': Decimal('80.00'), 'author__count': 0} {'id': 9, 'title': '跟老男孩學思想', 'publisher_id': 1, 'price': Decimal('90.00'), 'author__count': 0} '''
2,統計每一個出版社最便宜的書,
ret=models.Publisher.objects.annotate(Min('books__price')).values() for i in ret.values(): print(i)
3,統計不止一個做者的圖書,
#統計不止一個做者的圖書, ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1) print(ret)
4,查詢做者出的書的總價格
# 查詢做者出的書的總價格 ret=models.Author.objects.annotate(sum=Sum('books__price')).values() print(ret)
先進行導入
from django.db.models import F
示例代碼
# F查詢 from django.db.models import F # ret=models.Book.objects.filter(sale__gt=50).values() #F查詢,直接查出sale大於kucun的, ret=models.Book.objects.filter(sale__gt=F('kucun')).values() #還能夠加減數值 ret=models.Book.objects.filter(sale__gt=F('kucun')+30).values() print(ret)
對數據的修改:update與save的區別,save的效率要慢,
#對數據的修改, models.Book.objects.all().update(sale=100) #區分update與save的差異, book_obj=models.Book.objects.get(id=1) book_obj.sale=0 book_obj.save()
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。
若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象。
先進行導入
from django.db.models import Q
ret=models.Book.objects.filter(Q(id__lt=3)|Q(id__gt=5)) # print(ret) for i in ret: print(i) ret = models.Book.objects.filter(Q(id__gt=3)&Q(id__lt=9)) # print(ret) for i in ret: print(i)
還能夠進行取反
ret=models.Book.objects.filter(~Q(id__lt=3)|Q(id__gt=5)) # print(ret) for i in ret: print(i)
/
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() import datetime from app01 import models try: from django.db import transaction with transaction.atomic(): new_publisher = models.Publisher.objects.create(name="火星出版社") models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10) # 指定一個不存在的出版社id except Exception as e: print(str(e))
# extra # 在QuerySet的基礎上繼續執行子語句 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # select和select_params是一組,where和params是一組,tables用來設置from哪一個表 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 舉個例子: models.UserInfo.objects.extra( select={'newid':'select count(1) from app01_usertype where id>%s'}, select_params=[1,], where = ['age>%s'], params=[18,], order_by=['-age'], tables=['app01_usertype'] ) """ select app01_userinfo.id, (select count(1) from app01_usertype where id>1) as newid from app01_userinfo,app01_usertype where app01_userinfo.age > 18 order by app01_userinfo.age desc """ # 執行原生SQL # 更高靈活度的方式執行原生SQL語句 # from django.db import connection, connections # cursor = connection.cursor() # cursor = connections['default'].cursor() # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) # row = cursor.fetchone() ORM 執行原生SQL的方法
################################################################## # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # ################################################################## def all(self) # 獲取全部的數據對象 def filter(self, *args, **kwargs) # 條件查詢 # 條件能夠是:參數,字典,Q def exclude(self, *args, **kwargs) # 條件查詢 # 條件能夠是:參數,字典,Q def select_related(self, *fields) 性能相關:表之間進行join連表操做,一次性獲取關聯的數據。 總結: 1. select_related主要針一對一和多對一關係進行優化。 2. select_related使用SQL的JOIN語句進行優化,經過減小SQL查詢的次數來進行優化、提升性能。 def prefetch_related(self, *lookups) 性能相關:多表連表操做時速度會慢,使用其執行屢次SQL查詢在Python代碼中實現連表操做。 總結: 1. 對於多對多字段(ManyToManyField)和一對多字段,可使用prefetch_related()來進行優化。 2. prefetch_related()的優化方式是分別查詢每一個表,而後用Python處理他們之間的關係。 def annotate(self, *args, **kwargs) # 用於實現聚合group by查詢 from django.db.models import Count, Avg, Max, Min, Sum v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')) # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1) # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1) # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 def distinct(self, *field_names) # 用於distinct去重 models.UserInfo.objects.values('nid').distinct() # select distinct nid from userinfo 注:只有在PostgreSQL中才能使用distinct進行去重 def order_by(self, *field_names) # 用於排序 models.UserInfo.objects.all().order_by('-id','age') def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # 構造額外的查詢條件或者映射,如:子查詢 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) def reverse(self): # 倒序 models.UserInfo.objects.all().order_by('-nid').reverse() # 注:若是存在order_by,reverse則是倒序,若是多個排序則一一倒序 def defer(self, *fields): models.UserInfo.objects.defer('username','id') 或 models.UserInfo.objects.filter(...).defer('username','id') #映射中排除某列數據 def only(self, *fields): #僅取某個表中的數據 models.UserInfo.objects.only('username','id') 或 models.UserInfo.objects.filter(...).only('username','id') def using(self, alias): 指定使用的數據庫,參數爲別名(setting中的設置) ################################################## # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # ################################################## def raw(self, raw_query, params=None, translations=None, using=None): # 執行原生SQL models.UserInfo.objects.raw('select * from userinfo') # 若是SQL是其餘表時,必須將名字設置爲當前UserInfo對象的主鍵列名 models.UserInfo.objects.raw('select id as nid from 其餘表') # 爲原生SQL設置參數 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) # 將獲取的到列名轉換爲指定列名 name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) # 指定數據庫 models.UserInfo.objects.raw('select * from userinfo', using="default") ################### 原生SQL ################### from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) def values(self, *fields): # 獲取每行數據爲字典格式 def values_list(self, *fields, **kwargs): # 獲取每行數據爲元祖 def dates(self, field_name, kind, order='ASC'): # 根據時間進行某一部分進行去重查找並截取指定內容 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) # order只能是:"ASC" "DESC" # 並獲取轉換後的時間 - year : 年-01-01 - month: 年-月-01 - day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC') def datetimes(self, field_name, kind, order='ASC', tzinfo=None): # 根據時間進行某一部分進行去重查找並截取指定內容,將時間轉換爲指定時區時間 # kind只能是 "year", "month", "day", "hour", "minute", "second" # order只能是:"ASC" "DESC" # tzinfo時區對象 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC) models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """ pip3 install pytz import pytz pytz.all_timezones pytz.timezone(‘Asia/Shanghai’) """ def none(self): # 空QuerySet對象 #################################### # METHODS THAT DO DATABASE QUERIES # #################################### def aggregate(self, *args, **kwargs): # 聚合函數,獲取字典類型聚合結果 from django.db.models import Count, Avg, Max, Min, Sum result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid')) ===> {'k': 3, 'n': 4} def count(self): # 獲取個數 def get(self, *args, **kwargs): # 獲取單個對象 def create(self, **kwargs): # 建立對象 def bulk_create(self, objs, batch_size=None): # 批量插入 # batch_size表示一次插入的個數 objs = [ models.DDD(name='r11'), models.DDD(name='r22') ] models.DDD.objects.bulk_create(objs, 10) def get_or_create(self, defaults=None, **kwargs): # 若是存在,則獲取,不然,建立 # defaults 指定建立時,其餘字段的值 obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) def update_or_create(self, defaults=None, **kwargs): # 若是存在,則更新,不然,建立 # defaults 指定建立時或更新時的其餘字段 obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) def first(self): # 獲取第一個 def last(self): # 獲取最後一個 def in_bulk(self, id_list=None): # 根據主鍵ID進行查找 id_list = [11,21,31] models.DDD.objects.in_bulk(id_list) def delete(self): # 刪除 def update(self, **kwargs): # 更新 def exists(self): # 是否有結果 QuerySet方法大全
#統計不止一個做者的圖書,
ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
print(ret)