Django之ORM-model模型關係
模型類關係
1)一對多關係
例:圖書類-英雄類
models.ForeignKey() 定義在多的類中。
2)多對多關係
例:新聞類-新聞型別類 體育新聞 國際新聞
models.ManyToManyField() 定義在哪個類中都可以。
3)一對一關係
例:員工基本資訊類-員工詳細資訊類. 員工工號
models.OneToOneField定義在哪個類中都可以。
多對多示例
# 新聞型別類 class NewsType(models.Model): # 型別名 type_name = models.CharField(max_length=20) # 關係屬性,代表型別下面的資訊 type_news = models.ManyToManyField('NewsInfo') # 新聞類 class NewsInfo(models.Model): # 新聞標題 title = models.CharField(max_length=128) # 釋出時間 pub_date = models.DateTimeField(auto_now_add=True) # 資訊內容 content = models.TextField() # 關係屬性, 代表資訊所屬的型別 # news_type = models.ManyToManyField('NewsType')
# 員工基本資訊類 class EmployeeBasicInfo(models.Model): # 姓名 name = models.CharField(max_length=20) # 性別 gender = models.BooleanField(default=False) # 年齡 age = models.IntegerField() # 關係屬性,代表員工的詳細資訊 employee_detail = models.OneToOneField('EmployeeDetailInfo') # 員工詳細資訊類 class EmployeeDetailInfo(models.Model): # 聯絡地址 addr = models.CharField(max_length=256) # 教育經歷 # 關係屬性,代表員工基本資訊 # employee_basic = models.OneToOneField('EmployeeBasicInfo')
重點關注一對多的關係;
模型-關聯查詢
關聯查詢-一對多
查詢和物件關聯的資料
在一對多關係中,一對應的類我們把它叫做一類,多對應的那個類我們把它叫做多類,我們把多類中定義的建立關聯的類屬性叫做關聯屬性。
例:查詢id為1的圖書關聯的英雄的資訊。
b=BookInfo.objects.get(id=1) b.heroinfo_set.all() 通過模型類查詢: HeroInfo.objects.filter(hbook__id=1)
例:查詢id為1的英雄關聯的圖書資訊。
h = HeroInfo.objects.get(id=1) h.hbook 通過模型類查詢: BookInfo.objects.filter(heroinfo__id=1)
格式:
由一類的物件查詢多類的時候:
一類的物件.多類名小寫_set.all() #查詢所用資料
由多類的物件查詢一類的時候:
多類的物件.關聯屬性 #查詢多類的物件對應的一類的物件
由多類的物件查詢一類物件的id時候:
多類的物件. 關聯屬性_id
通過模型類實現關聯查詢
關聯查詢
1.通過模型類實現關聯查詢時,要查哪個表中的資料,就需要通過哪個類來查。
2.寫關聯查詢條件的時候,如果類中沒有關係屬性,條件需要些對應類的名,如果類中有關係屬性,直接寫關係屬性。
例:查詢圖書資訊,要求圖書關聯的英雄的描述包含'八'。
BookInfo.objects.filter(heroinfo__hcomment__contains='八')
例:查詢圖書資訊,要求圖書中的英雄的id大於3.
BookInfo.objects.filter(heroinfo__id__gt=3)
例:查詢書名為“天龍八部”的所有英雄。
HeroInfo.objects.filter(hbook__btitle='天龍八部')
通過多類的條件查詢一類的資料:
一類名.objects.filter(多類名小寫__多類屬性名__條件名)
通過一類的條件查詢多類的資料:
多類名.objects.filter(關聯屬性__一類屬性名__條件名)
模型-插入和刪除
插入、更新和刪除
呼叫一個模型類物件的save方法的時候就可以實現對模型類對應資料表的插入和更新。
呼叫一個模型類物件的delete方法的時候就可以實現對模型類對應資料表資料的刪除。
插入示例:
# 1.建立bookinfo物件 b = models.BookInfo() b.btitle = "流星蝴蝶劍" b.bpub_date = date(1990, 1, 1) # 2.儲存進資料庫 b.save()
刪除示例:
# 1.獲取書籍物件 book = models.BookInfo.objects.get(id=bid) # 2.刪除書籍 book.delete()
模型-自關聯
自關聯是一種特殊的一對多的關係。
案例:顯示廣州市的上級地區和下級地區。
地區表:id, atitle, aParent_id;
mysql終端中批量執行sql語句:source areas.sql;
自關聯案例
models.py
class AreaInfo(models.Model): """地區模型類""" # 地區名稱 atitle = models.CharField(max_length=20) # 關係屬性,代表當前地區的父級地區 aParent = models.ForeignKey("self", null=True, blank=True)
E:\Pycharm\Pycharm_save\cp15\test2>cd booktest E:\Pycharm\Pycharm_save\cp15\test2\booktest>mysql -uroot -p Enter password: **** Welcome to the MySQL monitor. Commands end with ; or \g. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use test1000; Database changed mysql> source area.sql
area.html
<h1>地區</h1> <p>{{ area }}</p> <h1>父級地區</h1> <p>{{ parent }}</p> <h1>子級地區</h1> <ul> {% for child in children %} <li>{{ child }}</li> {% endfor %} </ul>
Views.py
def areas(request): '''獲取廣州市的上級地區和下級地區''' # 1.獲取廣州市的資訊 area = AreaInfo.objects.get(atitle='廣州市') # 2.查詢廣州市的上級地區 parent = area.aParent # 3.查詢廣州市的下級地址 children = area.areainfo_set.all() # 使用模板 return render(request, 'booktest/areas.html', {'area': area, 'parent': parent, 'children': children})
Urls.py
from django.conf.urls import url from booktest import views urlpatterns = [ url(r'^areas/$', views.areas), # 自關聯案例 ]
應注意瀏覽器中的url後面的’/’。
模型-模型管理器
什麼是管理器?
BookInfo.objects.all()->objects是一個什麼東西呢?
答:objects是Django幫我自動生成的管理器物件,通過這個管理器可以實現對資料的查詢。
objects是models.Manger類的一個物件。自定義管理器之後Django不再幫我們生成預設的objects管理器。
自定義管理器
可以在BookInfo下自定義一個 book = models.Manager()
這時就不能使用 BookInfo.objects.xxx了,而是BookInfo.book.xxx,但這樣並沒有什麼用。
我們一般這樣用:
- 1)自定義一個管理器類,這個類繼承models.Manger類。
- 2)再在具體的模型類裡定義一個自定義管理器類的物件。
自定義管理器類的應用場景
1)改變查詢的結果集。
比如呼叫BookInfo.books.all()返回的是沒有刪除的圖書的資料。
2)新增額外的方法。
管理器類中定義一個方法幫我們操作模型類對應的資料表。
使用self.model()就可以建立一個跟自定義管理器對應的模型類物件。
自定義管理器示例
自定義管理器程式碼
class BookInfoManager(models.Manager): '''圖書模型管理器類''' # 1.改變原有查詢的結果集 def all(self): # 1.呼叫父類的all方法,獲取所有資料 books = super().all() # QuerySet # 2.對books中的資料進行過濾 books = books.filter(isDelete=False) # 返回books return books # 2.封裝方法,操作模型類對應的資料表(增刪改查) def create_book(self, btitle, bpub_date): '''新增一本圖書''' # 1.建立一個圖書物件 # 獲取self所在的模型類 model_class = self.model book = model_class() # book = models.BookInfo() book.btitle = btitle book.bpub_date = bpub_date # 2.新增進資料庫 book.save() # 3.返回book return book # 一類 # booktest2_bookinfo class BookInfo(models.Model): '''圖書模型類''' # 圖書名稱 btitle = models.CharField(max_length=20, db_column='title') # 圖書名字唯一 # btitle = models.CharField(max_length=20, unique=True, db_index=True) # 價格,最大位數為10,小數為2 # bprice = models.DecimalField(max_digits=10, decimal_places=2) # 出版日期 bpub_date = models.DateField() # bpub_date = models.DateField(auto_now_add=True) # 建立時間 # bpub_date = models.DateField(auto_now=True) # 更新時間 # 閱讀量 bread = models.IntegerField(default=0) # 評論量 bcomment = models.IntegerField(default=0) # 刪除標記 isDelete = models.BooleanField(default=False) # book = models.Manager() # 自定一個Manager類物件,管理器物件 objects = BookInfoManager() # 自定義一個BookInfoManager類的物件 # @classmethod # def create_book(cls, btitle, bpub_date): # '''新增一本圖書''' # # 建立一個cls類的物件 # obj = cls() # obj.btitle = btitle # obj.bpub_date = bpub_date # # 新增進資料庫 # obj.save() # # 返回obj # return obj自定義管理器程式碼
自定義管理器的使用:
1.BookInfo.objects.all() # objects是管理器中的objects,返回的是一個isDelete=0的值;
2.
from booktest.models import BookInfo
BookInfo.objects.create_book('test2', '1991-1-1')
其實在models.Manager裡面已經封裝了create方法,使用示例如下:
BookInfo.objects.create(btitlt='test3', bpub_date='1991-1-1')
應注意如果定義的圖書模型類名換了比如class BookInfo,這個時候BookInfoManager中的book = BookInfo()也要改成
book = BookInfo1(),這樣會很麻煩,但幸好,Manager裡面有考慮到這一點,
# 獲取self所在的模型類 model_class = self.model book = model_class() # 上面兩句相當於最後一句。 # book = BookInfo()
小結:
主旨:模型管理器類和模型類是通過在模型類中定義objects = BookInfoManager(),在模型管理器類中通過
model_class = self.model; book = model_class() 來建立關係的。
模型-元選項
Django預設生成的表名:應用名小寫_模型類名小寫。
元選項:需要在模型類中定義一個元類Meta,在裡面定義一個類屬性db_table就可以指定表名。
如果改了應用名,而表名有不會自動更改,這個時候,就會出問題;
為了解決這個問題,我們要讓模型類的表名不依賴於應用名;
使用 元選項,指定表名。
class BookInfo(models.Model): '''圖書模型類''' btitle = models.CharField(max_length=20, db_column='title') bpub_date = models.DateField() bread = models.IntegerField(default=0) bcomment = models.IntegerField(default=0) isDelete = models.BooleanField(default=False) objects = BookInfoManager() # 自定義一個BookInfoManager類的物件
# 使用元選項 class Meta: db_table = 'bookinfo' # 指定模型類對應表名
&n