天天看點

Django ORM – 多表執行個體

表與表之間的關系可分為以下三種:

一對一: 一個人對應一個身份證号碼,資料字段設定 unique。

一對多: 一個家庭有多個人,一般通過外鍵來實作。

多對多: 一個學生有多門課程,一個課程有很多學生,一般通過第三個表來實作關聯。

Django ORM – 多表執行個體

接下來我們來看下多表多執行個體。

class Book(models.Model):

    title = models.CharField(max_length=32)

    price = models.DecimalField(max_digits=5, decimal_places=2)

    pub_date = models.DateField()

    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)

    authors = models.ManyToManyField("Author")

class Publish(models.Model):

    name = models.CharField(max_length=32)

    city = models.CharField(max_length=64)

    email = models.EmailField()

class Author(models.Model):

    age = models.SmallIntegerField()

    au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)

class AuthorDetail(models.Model):

    gender_choices = (

        (0, "女"),

        (1, "男"),

        (2, "保密"),

    )

    gender = models.SmallIntegerField(choices=gender_choices)

    tel = models.CharField(max_length=32)

    addr = models.CharField(max_length=64)

    birthday = models.DateField()

說明:

1、EmailField 資料類型是郵箱格式,底層繼承 CharField,進行了封裝,相當于 MySQL 中的 varchar。

2、Django1.1 版本不需要聯級删除:on_delete=models.CASCADE,Django2.2 需要。

3、一般不需要設定聯級更新.

4、外鍵在一對多的多中設定:models.ForeignKey("關聯類名", on_delete=models.CASCADE)。

5、OneToOneField = ForeignKey(...,unique=True)設定一對一。

6、若有模型類存在外鍵,建立資料時,要先建立外鍵關聯的模型類的資料,不然建立包含外鍵的模型類的資料時,外鍵的關聯模型類的資料會找不到。

書籍表 Book:title 、 price 、 pub_date 、 publish(外鍵,多對一) 、 authors(多對多)

出版社表 Publish:name 、 city 、 email

作者表 Author:name 、 age 、 au_detail(一對一)

作者詳情表 AuthorDetail:gender 、 tel 、 addr 、 birthday

以下是表格關聯說明:

Django ORM – 多表執行個體

我們在 MySQL 中執行以下 SQL 插入操作:

Django ORM – 多表執行個體

方式一: 傳對象的形式,傳回值的資料類型是對象,書籍對象。

步驟:

a. 擷取出版社對象

b. 給書籍的出版社屬性 pulish 傳出版社對象

def add_book(request):

    #  擷取出版社對象

    pub_obj = models.Publish.objects.filter(pk=1).first()

    #  給書籍的出版社屬性publish傳出版社對象

    book = models.Book.objects.create(title="菜鳥教程", price=200, pub_date="2010-10-10", publish=pub_obj)

    print(book, type(book))

    return HttpResponse(book)

Django ORM – 多表執行個體

方式二: 傳對象 id 的形式(由于傳過來的資料一般是 id,是以傳對象 id 是常用的)。

一對多中,設定外鍵屬性的類(多的表)中,MySQL 中顯示的字段名是:外鍵屬性名_id。

傳回值的資料類型是對象,書籍對象。

a. 擷取出版社對象的 id

b. 給書籍的關聯出版社字段 pulish_id 傳出版社對象的 id

    #  擷取出版社對象的id

    pk = pub_obj.pk

    #  給書籍的關聯出版社字段 publish_id 傳出版社對象的id

    book = models.Book.objects.create(title="沖靈劍法", price=100, pub_date="2004-04-04", publish_id=pk)

Django ORM – 多表執行個體

方式一: 傳對象形式,無傳回值。

a. 擷取作者對象

b. 擷取書籍對象

c. 給書籍對象的 authors 屬性用 add 方法傳作者對象

    #  擷取作者對象

    chong = models.Author.objects.filter(name="令狐沖").first()

    ying = models.Author.objects.filter(name="任盈盈").first()

    #  擷取書籍對象

    book = models.Book.objects.filter(title="菜鳥教程").first()

    #  給書籍對象的 authors 屬性用 add 方法傳作者對象

    book.authors.add(chong, ying)

Django ORM – 多表執行個體

方式二: 傳對象id形式,無傳回值。

a. 擷取作者對象的 id

c. 給書籍對象的 authors 屬性用 add 方法傳作者對象的 id

    #  擷取作者對象的id

    pk = chong.pk

    book = models.Book.objects.filter(title="沖靈劍法").first()

    #  給書籍對象的 authors 屬性用 add 方法傳作者對象的id

    book.authors.add(pk)

Django ORM – 多表執行個體

前提:

多對多(雙向均有關聯管理器)

一對多(隻有多的那個類的對象有關聯管理器,即反向才有)

文法格式:

注意:一對多隻能反向

常用方法:

add():用于多對多,把指定的模型對象添加到關聯對象集(關系表)中。

注意:add() 在一對多(即外鍵)中,隻能傳對象( *QuerySet資料類型),不能傳 id(*[id表])。

*[ ] 的使用:

# 方式一:傳對象

book_obj = models.Book.objects.get(id=10)

author_list = models.Author.objects.filter(id__gt=2)

book_obj.authors.add(*author_list)  # 将 id 大于2的作者對象添加到這本書的作者集合中

# 方式二:傳對象 id

book_obj.authors.add(*[1,3]) # 将 id=1 和 id=3 的作者對象添加到這本書的作者集合中

return HttpResponse("ok")

Django ORM – 多表執行個體

反向:小寫表名_set

ying = models.Author.objects.filter(name="任盈盈").first()

book = models.Book.objects.filter(title="沖靈劍法").first()

ying.book_set.add(book)

Django ORM – 多表執行個體

create():建立一個新的對象,并同時将它添加到關聯對象集之中。

傳回新建立的對象。

pub = models.Publish.objects.filter(name="明教出版社").first()

wo = models.Author.objects.filter(name="任我行").first()

book = wo.book_set.create(title="吸星大法", price=300, pub_date="1999-9-19", publish=pub)

print(book, type(book))

Django ORM – 多表執行個體

remove():從關聯對象集中移除執行的模型對象。

對于 ForeignKey 對象,這個方法僅在 null=True(可以為空)時存在,無傳回值。

author_obj =models.Author.objects.get(id=1)

book_obj = models.Book.objects.get(id=11)

author_obj.book_set.remove(book_obj)

Django ORM – 多表執行個體

clear():從關聯對象集中移除一切對象,删除關聯,不會删除對象。

對于 ForeignKey 對象,這個方法僅在 null=True(可以為空)時存在。

無傳回值。

#  清空獨孤九劍關聯的所有作者

book = models.Book.objects.filter(title="菜鳥教程").first()

book.authors.clear()

基于對象的跨表查詢。

查詢主鍵為 1 的書籍的出版社所在的城市(正向)。

book = models.Book.objects.filter(pk=10).first()

res = book.publish.city

print(res, type(res))

Django ORM – 多表執行個體

查詢明教出版社出版的書籍名(反向)。

反向:對象.小寫類名_set(pub.book_set) 可以跳轉到關聯的表(書籍表)。

pub.book_set.all():取出書籍表的所有書籍對象,在一個 QuerySet 裡,周遊取出一個個書籍對象。

res = pub.book_set.all()

for i in res:

    print(i.title)

Django ORM – 多表執行個體

查詢令狐沖的電話(正向)

正向:對象.屬性 (author.au_detail) 可以跳轉到關聯的表(作者詳情表)

author = models.Author.objects.filter(name="令狐沖").first()

res = author.au_detail.tel

Django ORM – 多表執行個體

查詢所有住址在黑木崖的作者的姓名(反向)。

一對一的反向,用 對象.小寫類名 即可,不用加 _set。

反向:對象.小寫類名(addr.author)可以跳轉到關聯的表(作者表)。

addr = models.AuthorDetail.objects.filter(addr="黑木崖").first()

res = addr.author.name

Django ORM – 多表執行個體

菜鳥教程所有作者的名字以及手機号(正向)。

正向:對象.屬性(book.authors)可以跳轉到關聯的表(作者表)。

作者表裡沒有作者電話,是以再次通過對象.屬性(i.au_detail)跳轉到關聯的表(作者詳情表)。

res = book.authors.all()

    print(i.name, i.au_detail.tel)

Django ORM – 多表執行個體

查詢任我行出過的所有書籍的名字(反向)。

author = models.Author.objects.filter(name="任我行").first()

res = author.book_set.all()

Django ORM – 多表執行個體

查詢菜鳥出版社出版過的所有書籍的名字與價格。

res = models.Book.objects.filter(publish__name="菜鳥出版社").values_list("title", "price")

Django ORM – 多表執行個體

反向:通過 小寫類名__跨表的屬性名稱(book__title,book__price) 跨表擷取資料。

res = models.Publish.objects.filter(name="菜鳥出版社").values_list("book__title","book__price")

Django ORM – 多表執行個體

查詢任我行出過的所有書籍的名字。

正向:通過 屬性名稱__跨表的屬性名稱(authors__name) 跨表擷取資料:

反向:通過 小寫類名__跨表的屬性名稱(book__title) 跨表擷取資料:

Django ORM – 多表執行個體

查詢任我行的手機号。

正向:通過 屬性名稱__跨表的屬性名稱(au_detail__tel) 跨表擷取資料。

Django ORM – 多表執行個體

反向:通過 小寫類名__跨表的屬性名稱(author__name) 跨表擷取資料。

Django ORM – 多表執行個體