1、單表操做git
# 單表查詢操做基本方法 class BookList(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) # 總共8位,小數佔2位 publist_date = models.DateField() # DateField年月日,DateTimeField詳細時間 #單獨測試models.py文件 # 將manage.py中前4行拷貝到一個新的test.py文件中 import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day20.settings") import django django.setup() from app01 import models # 插入語句 # book_obj = models.BookList.objects.create(title="三國演義",price=1123.22,publist_date='2019-08-28') # import datetime # ctime = datetime.datetime.today() # book_obj = models.BookList.objects.create(title="紅樓夢",price=1666.22,publist_date=ctime) # print(book_obj) # BookList object # 更新數據 # models.BookList.objects.filter(title="三國演義").update(price=1123.22) # queryset方法都是批量更新操做 # 查詢 # print(models.BookList.objects.all()) # <QuerySet [<BookList: 三國演義>, <BookList: 紅樓夢>]> # print(models.BookList.objects.filter(pk=1)) # <QuerySet [<BookList: 三國演義>]> # 推薦使用 # # get獲取到的就是數據對象自己,可是條件不知足的時候會直接報錯,不推薦使用 # print(models.BookList.objects.get(pk=3)) # 紅樓夢 # 刪除 # models.BookList.objects.filter(pk=1).delete() # 更多查詢方法 # exclude取反 # print(models.BookList.objects.exclude(pk=1)) # values 拿對應的字段,返回的是列表套字典 # print(models.BookList.objects.values('title','price')) # <QuerySet [{'title': '三國演義', 'price': Decimal('1123.22')}, {'title': '紅樓夢', 'price': Decimal('1666.22')}]> # value_list 返回的是列表套元組 # print(models.BookList.objects.values_list('title','price')) # <QuerySet [('三國演義', Decimal('1123.22')), ('紅樓夢', Decimal('1666.22'))]> # order by 查詢結果排序 默認升序 # print(models.BookList.objects.order_by('price')) # <QuerySet [<BookList: 三國演義>, <BookList: 紅樓夢>]> # 降序 # print(models.BookList.objects.order_by('price').reverse()) # 去重:去重的前提是:數據必須是徹底同樣的 # print(models.BookList.objects.filter(title="三國演義").values('title','price').distinct()) # <QuerySet [{'title': '三國演義', 'price': Decimal('1123.22')}]> # count() # print(models.BookList.objects.all().count()) # first/last # print(models.BookList.objects.first()) # print(models.BookList.objects.last()) # exists # print(models.BookList.objects.filter(pk=2).exists())
# 13個必須會的操做 # 返回QuerySet對象的方法有 all() 查詢全部結果 filter() 它包含了與所給篩選條件相匹配的對象 exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 order_by() reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用(在model類的Meta中指定ordering或調用order_by()方法) distinct(): 從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重 # 特殊的QuerySet values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列 values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 # 返回具體對象的 get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤 first() : 第一條記錄 last() : 最後一條記錄 # 返回布爾值的方法有 exists(): 若是QuerySet包含數據,就返回True,不然返回False # 返回數字的方法有 count(): 返回數據庫中匹配查詢(QuerySet)的對象數量
2、單表查詢之雙下劃線操做sql
models.Tb1.objects.filter(id__lte=10, id__gt=1) # 獲取id大於1 且 小於等於10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、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(datetime__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周來表示,由於天數是不肯定的
3、圖書管理系統表設計django
表關係
一對一
一對多
多對多
ps:站在兩邊判斷是否能夠同時有多個對方
若是均可以 那麼就是多對多
若是是單向的一對多 那麼就是一對多
若是都不是 要麼沒有任何關係 要麼就是一對一
Book 書籍
Publish 出版社
Author 做者
AuthorDetail 做者詳情
書和出版社 就是一個一對多
書和做者 多對多
做者和做者詳情 一對一
# models.py 表結構 """ 一對多 :外鍵字段 一般建在多的一方 多對多 :外鍵字段 不管建在哪一方均可以,可是推薦建在查詢頻率較高的表 一對一 :外鍵字段 不管建在哪一方均可以,可是推薦建在查詢頻率較高的表 """ class Book(models.Model): title = models.CharField(max_length=32) price = models.CharField(max_length=32) publish_date = models.DateField(auto_now_add=True) # 出版社外鍵 publish = models.ForeignKey(to='Publish') # 默認關聯的就是Publist表的主鍵字段 # 做者外鍵 authors = models.ManyToManyField(to='Author') # 默認關聯的就是Author表的主鍵字段 # 一對多外鍵字段,在書寫的時候,orm會自動加_id後綴 """多對多字段是虛擬字段,不會在表中展現出來 只是用來告訴django orm 自動 建立書籍和做者的第三張表 還能夠跨表查詢的時候提供方便 """ class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField addr = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.CharField(max_length=3) male = models.CharField(max_length=1) # 一對一 # 一對一外鍵字段,在書寫的時候,orm會自動加_id後綴 author_detail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model): phone = models.CharField(max_length=32) addr = models.CharField(max_length=32)
#數據本身僞造就能夠 """ ORM 聯表操做 """ # 外鍵字段的增 # models.Book.objects.create(title='三國演義',price='98.5',publish_id=1) # models.Book.objects.create(title='紅樓夢',price='128.88',publish_id=1) # models.Book.objects.create(title='密卷',price='58',publish_id=4) # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='西遊記',price='90',publish=publish_obj) # 改 # models.Book.objects.filter(pk=1).update(publish_id=3) # 虛擬對象直接傳字段 # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.filter(pk=1).update(publist=publish_obj) # 做者和書籍綁定關係 # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.authors.add(1) # 在第三張表book_authors中,添加書籍和做者的關係,也能夠添加2條add(1,2),2本書是這個做者寫的 # author_obj1 = models.Author.objects.filter(pk=1).first() # author_obj2 = models.Author.objects.filter(pk=2).first() # book_obj.authors.add(author_obj1,author_obj2) """ add既支持傳數字,也支持傳對象,二者也均可以是多個 """ # 改 # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.authors.set([2,]) """ set既支持傳數字,也支持傳對象,二者也均可以是多個 注意:傳入的格式必須是可迭代對象 """ # 刪 # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.authors.remove(2) """ remove既支持傳數字,也支持傳對象,二者均可以是多個 """ # 清空 book_obj = models.Book.objects.filter(pk=1).first() book_obj.authors.clear() # 清空當前數據全部的關聯信息 """ clear()內不須要傳任何參數 """
4、Django終端打印SQL語句app
# settings.py文件中,加了這段話後,會將django執行的sql語句都打印出來 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } } # SELECT `app01_book`.`title` FROM `app01_publish` INNER JOIN `app01_book` ON (`app01_publish`.`id` = `app01_book`.`publish_id`)
WHERE (`app01_publish`.`name` = '南方出版社' AND `app01_book`.`price` > '19') LIMIT 21; args=('南方出版社', '19')
5、ORM多表查詢測試
# 正向與反向的概念解釋 正向查詢按字段(字典建表時的關聯字段) 反向查詢按表名小寫... # 一對一 # 正向:author---關聯字段在author表裏--->authordetail 按字段 # 反向:authordetail---關聯字段在author表裏--->author 按表名小寫 # 查詢jason做者的手機號 正向查詢 # 查詢地址是 :山東 的做者名字 反向查詢 # 一對多 # 正向:book---關聯字段在book表裏--->publish 按字段 # 反向:publish---關聯字段在book表裏--->book 按表名小寫_set.all() 由於一個出版社對應着多個圖書 # 多對多 # 正向:book---關聯字段在book表裏--->author 按字段 # 反向:author---關聯字段在book表裏--->book 按表名小寫_set.all() 由於一個做者對應着多個圖書
5.1 基於對象的跨表查詢:子查詢spa
# 基於對象的跨表查詢 # 查詢書籍id爲1的出版社名稱(正向) # book_obj = models.Book.objects.filter(pk=1).first() # print(book_obj.publish) # Publish object # print(book_obj.publish.name) #南方出版社 # 查詢南方出版社出版過的書的名字(反向) # publish_obj = models.Publish.objects.filter(name="南方出版社").first() # print(publish_obj.book_set) # app01.Book.None 意味着語句沒寫全,_set說明有多個結果 # print(publish_obj.book_set.all()) # <QuerySet [<Book: Book object>, <Book: Book object>]> # 查詢做者simon的手機號(正向) # author_obj = models.Author.objects.filter(name="simon").first() # print(author_obj.author_detail.phone) # 根據手機號150查做者(反向) # authordetail_obj = models.AuthorDetail.objects.filter(phone=150).first() # print(authordetail_obj.author.name)
# 反向查詢:根據做者simon查詢手機號
res1 = models.AuthorDetail.objects.filter(author__name='simon').values('phone')
print(res1)
# 反向查詢:查詢年齡和手機號
res =models.AuthorDetail.objects.filter(author__name='simon').values('author__age','phone')
# 多對多 # 查詢書籍ID爲1的做者姓名 # book_obj = models.Book.objects.filter(pk=1).first() # print(book_obj.authors.all()) # <QuerySet [<Author: Author object>, <Author: Author object>]> # 查詢做者ID爲1的寫的書(反向) # author_obj = models.Author.objects.filter(pk=1).first() # print(author_obj.book_set.all())
5.2 基於雙下劃線的多表查詢設計
# 查詢書籍id爲1的做者的姓名:2張表沒有直接關聯,須要經過book_authors來關聯(正向) res1 = models.Book.objects.filter(id=1).values('authors') print(res1) # <QuerySet [{'authors': 2}, {'authors': 4}]> 查詢到做者ID res = models.Book.objects.filter(id=1).values('authors__name') print(res) # 做者名:<QuerySet [{'authors__name': 'jace'}, {'authors__name': 'once'}]> 做者姓名是once寫過的書的價格(反向) res = models.Author.objects.filter(name='once').values('book__price','book__title') print(res) # <QuerySet [{'book__price': '98.5', 'book__title': '三國演義'}]> # 查詢書籍id爲1的出版社addr(正向) res = models.Book.objects.filter(id=1).values('publish__addr') # 這裏的publish不是表面小寫而是字段 print(res) # <QuerySet [{'publish__addr': '上海'}]> # 經過出版社id=1找出版過的書(反向) res = models.Publish.objects.filter(id=1).values('book__title') print(res) # <QuerySet [{'book__title': '紅樓夢'}]> # 查詢紅樓夢做者的電話號碼(正向) res = models.Book.objects.filter(title="紅樓夢").values('authors__author_detail__phone') print(res) # <QuerySet [{'authors__author_detail__phone': '150'}]> # 查詢做者電話號碼是150出版過的書籍(反向) res = models.AuthorDetail.objects.filter(phone=150).values('author__book__title') print(res) # <QuerySet [{'author__book__title': '紅樓夢'}, {'author__book__title': '考卷'}]>
5.3 聯合查詢code
# 查詢北方出版社出版的的價格大於19的書 res = models.Book.objects.filter(price__gt='19',publish__name="北方出版社") print(res) # <QuerySet [<Book: Book object>]> # 查詢南方出版社出版過的書,且價格大於19(反向) res = models.Publish.objects.filter(name="南方出版社",book__price__gt=19).values('book__title') print(res) # <QuerySet [{'book__title': '三國演義'}, {'book__title': '18歲的天空'}]>
5.4 聚合查詢與分組查詢orm
from django.db.models import Avg,Sum,Max,Min,Count # 聚合查詢 # 請全部書籍的平均價格 res = models.Book.objects.all().aggregate(Avg("price")) print(res) # 分組查詢(group_by) # 統計每本書做者的個數 book_list = models.Book.objects.all().annotate(author_num=Count("authors")) for obj in book_list: print(obj.author_num) # 統計每一個出版社賣的最便宜的書 res = models.Publish.objects.annotate(min_price=Min("book__price"))
print([i.min_price for i in res ]) # for obj in res: # print(obj.min_price) #第二種方法: res = models.Book.objects.values("publish__name").annotate(min_price=Min("price")) print(res) # <QuerySet [{'publish__name': '工業出版社', 'min_price': '128.88'}, {'publish__name': '北方出版社', 'min_price': '90'}, {'publish__name': '南方出版社', 'min_price': '38'},
# {'publish__name': '武漢出版社', 'min_price': '38'}]> # 統計不僅一個做者的書 res = models.Book.objects.annotate(authors_num=Count("authors")).filter(authors_num__gt=1) print(res) # <QuerySet [<Book: Book object>]>
5.5 F 與 Q
# F查詢:查詢的條件左右兩邊都來自於數據庫而非你本身定義 # F能夠幫咱們取到表中某個字段對應的值來看成個人篩選條件,而不是我認爲自定義常量的條件了,實現了動態比較的效果:F 能夠幫咱們實現同一表中2個字段進行比較 from django.db.models import F,Q # 查詢賣出數大於庫存數的書籍 # sell_book和kc_book爲字段名 res = models.Book.objects.filter(sell_book__gt=F('kc_book')).values('title') print(res) # 將每一個商品的價格提升50元 res2 = models.Book.objects.update(price=F('price') + 50) # Q查詢:可以將filter內部默認的and關係,轉換成 與或非 # 逗號 默認也是 與 的關係 # 與& 或| 非~ # 查詢書籍名字是西遊記或價格是140的書籍 res = models.Book.objects.filter(Q(title="西遊記")|Q(price=140)).values('title') # res = models.Book.objects.filter(title="西遊記",price=140).values('title') print(res) # 非 ~Q # 查詢書籍價格不是140的書籍名 res1 = models.Book.objects.filter(~Q(price=140)).values("title") print(res1)
多對多表關係三種建立方式
1.全自動:ManyToManyField()自動建立第三張表 authors = models.ManyToManyField(to='Author') 讓django orm自動幫你建立第三張表 好處:不須要本身手動添加 壞處:表字段的擴展性極差 只會幫你建外鍵字段 其餘額外字段一律沒法建立 2.純手動(瞭解):沒法使用跨表查詢,必須本身一個表一個表手動查找 class Book(models.Model): name = ... class Author(models.Model): name = ... class Book2Author(models.Model): book_id = models.ForeignKey(to='Book') author_id = models.ForeignKey(to='Author') 3.半自動:可使用跨表查詢,與全自動同樣
優勢:能夠本身加額外的字段 class Book(models.Model): name = ... authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author')) class Author(models.Model): name = ...
# 若是外鍵建在這張表 # books = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('author','book')) class Book2Author(models.Model): book = models.ForeignKey(to='Book') author = models.ForeignKey(to='Author') create_time = ... info = ...