91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Django之模型層多表操作的實現

發布時間:2020-10-10 18:41:25 來源:腳本之家 閱讀:156 作者:W的一天 欄目:開發技術

一、創建模型

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

步驟如下:

Django之模型層多表操作的實現

Django之模型層多表操作的實現

5,數據庫遷移

Django之模型層多表操作的實現

由于Django默認就是db.sqlite,所以我們不用去settings配置,也不需要在項目的__init__.py里寫代碼,現在只需要輸入兩條數據庫遷移指令就行了

Django之模型層多表操作的實現

點擊這里之后進入:

Django之模型層多表操作的實現

在這里數輸入指令,就不需要寫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月份的書籍

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泰安市| 登封市| 安国市| 缙云县| 长垣县| 潜山县| 社会| 永平县| 新田县| 五莲县| 彭阳县| 高州市| 东城区| 宁南县| 宽城| 铜陵市| 弋阳县| 剑阁县| 清原| 新竹市| 南投市| 伊吾县| 镇安县| 桃园县| 红原县| 安多县| 屏山县| 永川市| 汉川市| 吉林省| 永仁县| 虞城县| 贡山| 安福县| 南靖县| 泰来县| 元朗区| 高密市| 福清市| 西盟| 望奎县|