1. 程式人生 > >Django之ORM-model模型關係

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