您好,登錄后才能下訂單哦!
一、創建模型
1,一對多關系
一本書只有一個出版社,一個出版社可以出版多本書,從而書與出版社之間就構成一對多關系,書是‘多'的一方,出版社是‘一'的一方,我們在建立模型的時候,把外鍵寫在‘多'的一方,即我們要把外鍵寫在book類。
class Book(models.Model): name=models.CharField(max_length=15) price=models.IntegerField() publish=models.ForeignKey('Publish',on_delete=models.CASCADE) #這就是外鍵,其實是有三個參數的,第二參數是指向的字段,此處可以省略,他會自動指向id字段 class Publish(models.Model): name=models.CharField(max_length=15) addr=models.CharField(max_length=15) phone=models.IntegerField()
在創建模型時不用創建id字段,在makemigrations命令輸入之后,它會在migrations文件夾下生產一個py文件記錄models.py里面所有的改動,在記錄的時候就會自動給你加上自增長的主鍵字段id。
2,多對多關系
一本書可以有多個作者,一個作者可以寫多本書,從而書和作者就構成了多對多的關系,我們在創建模型的時候,把多對多關系寫在其中的任何一張表都可以。
class Book(models.Model): name=models.CharField(max_length=15) price=models.IntegerField() publish=models.CharField(max_length=15) author=models.ManyToManyField('Author',db_table='book_author') 這是創建關系表的代碼,由于是寫在book模型中的,所以第一個參數為另一張表Author,第二個參數為把關系表的名字改為‘book_author',如果不寫, 名字會是應用名_本模型名的小寫_另一張模型名的小寫。如‘app_book_author' class Meta: 這是把表名改為‘book',如果不寫,表名為APP名_模型名,如'app_book' db_table='book' class Author(models.Model): name=models.CharField(max_length=15) age=models.IntegerField() class Meta: db_table='author' 在創建第三張模型的時候也不用指定book的id和author的id,它會自動把兩個模型的id字段寫進去的
3,一對一關系
一個作者只能對應一個作者詳細信息表,他們之間就是一對一關系,這和多對多一樣的,關系寫在哪張表都是可以的
class Author(models.Model): name=models.CharField(max_length=15) age=models.IntegerField() author_info=models.OneToOneField('Author_Info',on_delete=models.CASCADE) 這是一對一關系創建,第二參數是,自動跟隨刪除,當作者不在了,隨即作者的信息也會刪除 class Meta: db_table='author' class Author_Info(models.Model): gf_name=models.CharField(max_length=10) telephone=models.IntegerField() ShenFenZheng=models.IntegerField()
4,在此處我們可以使用Django的database:db.sqlite3
步驟如下:
5,數據庫遷移
由于Django默認就是db.sqlite,所以我們不用去settings配置,也不需要在項目的__init__.py里寫代碼,現在只需要輸入兩條數據庫遷移指令就行了
點擊這里之后進入:
在這里數輸入指令,就不需要寫python manage.py了,因為已經進入到manage.py
現在輸入makemigrations指令 #記錄models.py文件發生的改變,然后在migrations文件夾下生產一個py文件,里面記錄發生的變化
再輸入migrate指令 #執行migrations文件下新變動的遷移文件,去更新數據庫
到此,表就創建成功了。
二、添加表記錄
1,一對多關系
之前我們創建了Book表和Publish表,兩者就是一對多的關系,Book表是‘多'的一方,所以外鍵字段在Book表,Book表添加和之前的不一樣,而‘一'的Publish表就是一張單表,和之前的一樣,所以我們只要學習‘多'的一張Book表的添加就行了。添加表記錄有兩種方式。
1.1 按models.py里面Book類的屬性來添加
pub=Publish.objects.all().filter(id=1).first() #首先找到id為1的Publish對象 book=Book.objects.create(name=name,price=price,publish=pub,pub_date=pub_date) #然后把這一對象賦值給Book類的publish屬性
1.2 按數據庫里面Book表的字段來添加
book=Book.objects.create(name=name,price=price,publish_id=1,pub_date=pub_date) #直接把Publish的id賦值給book表的publish_id就行了
2,多對多關系
之前我們創建了Book表和Author表,兩者就是多對多關系,我是把多對多關系寫在book表中的,所以從book去添加關聯關系是正向的。
# 當前生成的書籍對象 book_obj=Book.objects.create(title="追風箏的人",price=200,publishDate="2012-11-12",publish_id=1) # 為書籍綁定的作者對象 a1=Author.objects.filter(id=2).first() # 在Author表中主鍵為2的紀錄 a2=Author.objects.filter(id=1).first() # 在Author表中主鍵為1的紀錄 # 綁定多對多關系,即向關系表book_authors中添加紀錄,正向用屬性,反向用表名_set 第一種,以Book為基表,因為多對多關系是寫在Book中的,所以現在屬于正向關聯,用屬性 book_obj.author.add(author1,author2) #這是給book_obj對象綁定上author1和author2兩個對象。這里的author不是Author小寫,而是Book類的一個屬性 第二種,以Author為基表,因為多對多關系不是寫在Author表,所以屬于反向關聯,用表名小寫_set author_obj.book_set.add(book1,book2) #這是給author_obj對象綁定上book1和book2兩個對象,但是這里book可不是Author類的屬性,而且也沒有這個屬性,它是Book表小寫后得到的 關系表的方法: 1,add()方法 參數可以是可以是n個模型類對象,如上面的寫法 也可以是一個queryset集合,如author_list=Author.objects.filter(id__gt=2),這是找出id大于2的作者集合 book_obj.author.add(*author_list) 還可以是一個主鍵列表,如下面的寫法 book_obj.author.add(*[1,3,4]) 2,remove()方法,移出關系方法 現在book1關聯著author1和author2兩個作者 book1.author.remove(author1) #此時book1就關聯author2一個作者 反向也行author2.book_set.remove(book2) #把author2的關聯書籍book2給移出 3,clear()方法,清空關系方法 book1.author.clear() #把book1的所有關聯關系給刪除,現在book1就沒有關聯作者了 author1.book_set.clear() 一樣的,把author1的所有關聯書籍的關聯關系刪除 4,set()方法,先把關聯關系清空,再添加關聯關系 假如book1關聯著author1 book1.author.set(author2) 先把與author1的關聯關系刪除,然后再建立與author2的關聯關系 假如author3關聯著book1 author3.book_set.set(book2) 先把關聯關系清空,再建立與book2的關聯關系 5,=方法,賦值一個可迭代對象,關聯關系會被整體替換 假如book1關聯author1 new_list=[author2,author3] book1.author=new_list 這也會先把關聯關系清空,然后把列表里的對象與book1建立關聯關系
3,一對一關系
之前創建的Author表和Author_Info表之間就是一對一關系,我把關聯字段寫在了Author表中。
給Author類的屬性賦值 info=Author_Info.objects.create(gf_name=gf_name,telephone=telephone,ShenFenZheng=ShenFenZheng) #這是創建了一條Author_Info記錄,info就是一個Author_info對象 Author.objects.create(name=name,age=age,author_info=info) 把創建的info對象賦值給author_info屬性 和一對多一樣,也可以使用Author表的字段賦值 Author.objects.create(name=name,age=age,author_info_id=2)
三、基于對象的跨表查詢(就是子查詢)
1,一對多查詢(Book與Publish)
1.1 正向查詢(按屬性:publish)
# 查詢主鍵為1的書籍的出版社所在的城市 book_obj=Book.objects.filter(pk=1).first() # book_obj.publish 是主鍵為1的書籍對象關聯的出版社對象 print(book_obj.publish.city)
1.2 反向查詢(按表名小寫_set:book_set)
publish=Publish.objects.get(name="蘋果出版社") #publish.book_set.all() : 與蘋果出版社關聯的所有書籍對象集合 book_list=publish.book_set.all() for book_obj in book_list: print(book_obj.title)
2,一對一查詢(Author與Author_Info)
2.1 正向查詢(按屬性:author_info)
egon=Author.objects.filter(name="egon").first() print(egon.authorDetail.telephone)
2.2 反向查詢(按表名小寫:author)
# 查詢所有住址在北京的作者的姓名 authorDetail_list=AuthorDetail.objects.filter(addr="beijing") for obj in authorDetail_list: print(obj.author.name)
3,多對多查詢(Author與Book)
3.1 正向查詢(按屬性:author)
# 金瓶眉所有作者的名字以及手機號 book_obj=Book.objects.filter(title="金瓶眉").first() authors=book_obj.authors.all() for author_obj in authors: print(author_obj.name,author_obj.authorDetail.telephone)
3.2 反向查詢(按表名小寫_set:book_set)
# 查詢egon出過的所有書籍的名字 author_obj=Author.objects.get(name="egon") book_list=author_obj.book_set.all() #與egon作者相關的所有書籍 for book_obj in book_list: print(book_obj.title)
4,related_name設置
可以通過Foreignkey和MangToMangField的定義中設置related_name的值來復寫foo_set的名稱。 publish=ForeignKey('Publish',related_name='booklist') #這樣之后,反向就不用表名_set,就用booklist # 查詢 人民出版社出版過的所有書籍 publish=Publish.objects.get(name="人民出版社") book_list=publish.bookList.all() # 與人民出版社關聯的所有書籍對象集合
四、基于雙下劃線的跨表查詢
Django還提供了一種直觀而高效的方式在查詢中表示關聯關系,它能自動確認sql join聯系。要做跨關系查詢,就使用兩個下劃線來鏈接模型間關聯字段的名稱,直到最終連接到想要的model為止。
正向查詢按屬性,反向查詢按表名小寫
1,一對多查詢
# 練習: 查詢蘋果出版社出版過的所有書籍的名字與價格(一對多) # 正向查詢 按字段:publish queryResult=Book.objects .filter(publish__name="蘋果出版社") .values_list("title","price") # 反向查詢 按表名:book queryResult=Publish.objects .filter(name="蘋果出版社") .values_list("book__title","book__price")
2,多對多查詢
# 練習: 查詢alex出過的所有書籍的名字(多對多) # 正向查詢 按字段:authors: queryResult=Book.objects .filter(authors__name="yuan") .values_list("title") # 反向查詢 按表名:book queryResult=Author.objects .filter(name="yuan") .values_list("book__title","book__price")
3,一對一關系
# 查詢alex的手機號 # 正向查詢 ret=Author.objects.filter(name="alex").values("authordetail__telephone") # 反向查詢 ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
4,進階練習
# 練習: 查詢人民出版社出版過的所有書籍的名字以及作者的姓名 # 正向查詢 queryResult=Book.objects .filter(publish__name="人民出版社") .values_list("title","authors__name") # 反向查詢 queryResult=Publish.objects .filter(name="人民出版社") .values_list("book__title","book__authors__age","book__authors__name") # 練習: 手機號以151開頭的作者出版過的所有書籍名稱以及出版社名稱 # 方式1: queryResult=Book.objects .filter(authors__authorDetail__telephone__regex="151") .values_list("title","publish__name") # 方式2: ret=Author.objects .filter(authordetail__telephone__startswith="151") .values("book__title","book__publish__name")
五、聚合查詢與分組查詢
1,聚合
aggregate(*args,**kwargs)是Queryset的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的 計算所有圖書的平均價格 from django.db.models import Avg Book.objects.all().aggregate(Avg('price')) 結果:{'price__avg': 34.35} 如果你想要為聚合值指定一個名稱,可以向聚合函數前面用一個變量名來接收,此時,鍵的名稱就變為接收的變量名 Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} 在終止子句里面可以放多個聚合函數,得到結果就是有多個鍵值對 from django.db.models import Avg, Max, Min Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} aggregate()只能對一個分組有用,對于按某字段分完組后的n個組,此時aggregate()就不能循環對每個分組作用,它只會得到第一組的結果
2,分組
2.1 單表分組查詢
查詢每一個部門名稱以及對應的員工數 emp: id name age salary dep alex 12 2000 銷售部 egon 22 3000 人事部 wen 22 5000 人事部 emp.objects.values('dep').annotate(c=Count('*')) values(‘dep')就是按‘dep'進行分組 annotate()對每個分組的進行操作
2.2 多表分組查詢
每一個出版社的名稱和出版過的書籍個數 Publish.objects.values('name').annotate(c=Count('book')) #首先讀整個語句,當讀到‘book'時,就會把兩個表連起來,然后在按Publish.name分組 跨表分組查詢本質就是將關聯表join成一張表,然后再按單表的思路進行分組查詢 還有一種寫法: publishlist=Publish.objects.annotate(c=Count('book')) 這相當于給Publish表添加了一個‘c'字段。首先也是把兩張表連起來,以Publish分組,計算每個Publish的書籍數量 publishlist是一個queryset對象集合,里面放的是publish模型類對象,只是現在的對象比之前多了一個‘c'字段 for publish in publishlist: print(publish.name,publish.c) 利用for循環就可以遍歷出每個模型類對象,然后用句點符‘.'就可以取得任何字段的值 我們也可以不用for循環,直接用values_list()就可以實現,如上面的for循環可以寫成:values_list('name','c') 統計每一本書的作者個數 Book.objects.annotate(c=Count('author')).values_list('name','c') filter()放在annotate()前面就是相當于where 統計每一本以py開頭的書籍的作者的個數: Book.objects.filter(name__startswith='py').annotate(c=Count('author')).values_list('name','c') filter()放在annotate()后面就相當于having 統計作者個數大于1的書籍: Book.objects.annotate(c=Count('author')).filter(c__gt=1).value_list('name','c') 根據書籍的作者數來排序: Book.objects.annotate(c=Count('author')).orderby('c')
六、F查詢與Q查詢
1,F查詢
在之前,對象的字段只能放在比較符的前面,比如filter(id__gt=2),但現在,有一個表,有生物成績ss字段和物理成績ws字段,統計物理成績高于生物成績的學生: student.objects.filter(ws__gt=ss) 這樣寫肯定是報錯的,因為字段寫在了比較符后面,但此時我們借助F查詢就可以不報錯了,正確寫法如下: student.objcts.filter(ws__gt=F('ss')) F('ss')此時就是把ss字段的值取出來,就相當于一個純數字了,可以進行加減乘除操作 查詢物理成績大于生物成績兩倍的學生 student.objects.filter(ws__gt=F('ss')*2) 把每個學生的物理成績加上10分: student.objects.all().update(ws=F('ws')+10)
2,Q查詢
之前我們在用filter()時,可以用‘,'表示與關系,但沒有或關系,現在我們用Q查詢就可以實現或關系 Book.objects.filter(Q(id__gt=2)|Q(title__startswith='p')) 過濾出id大于2或者以‘p'開頭的 Book.objects.filter(Q(id__gt=2)&Q(title__startswith='p')) 過濾出id大于2且以‘p'開頭的 Book.objects.filter(Q(id__gt=2)|~Q(title__startswith='p')) 過濾出id大于2或不以‘p'開頭的 Q查詢可以和關鍵字參數混用,但Q()在前面 Book.objects.filter(Q(pub_date__year=2017)|Q(pub_date__year=2016),pub_date__month=2)過濾出2017年2月份或2016年2月份的書籍
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。