1. 程式人生 > >Django 模型層之多表操作

Django 模型層之多表操作

一.建立模型

例項:

作者表:
    擁有欄位:姓名(name),性別(sex),該表與書籍表之間為多對多的關係
作者詳情表:
    擁有欄位:地址(addr),手機號(phone),該表與作者表之間為一對一的關係
出版社表:
    擁有欄位:名字(name),地址(addr),該表與書籍表之間為一對多的關係
書籍表:
    擁有欄位:書名(name),單價(price)
分析:一本書可以擁有多個作者,一個作者可以寫多本書,所有作者與書籍之間為多對多的關聯關係(Many-To-Many);一本書只有一個出版社,但是一個出版社可以出版多種書籍,所以出版社和書籍之間是一對多的關聯關係(One-To-Many);作者與作者詳情就是一對一關聯關係(One-To-One)

所以在Models.py下建立模型如下

class Publish(models.Model):
    name = models.CharField(max_length=255)
    addr = models.CharField(max_length=255)

    def __str__(self):
        return self.name


class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)
    sex = models.IntegerField()
    authordetail = models.OneToOneField(to='AuthorDetail')

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    id = models.AutoField(primary_key=True)
    addr = models.CharField(max_length=255)
    phone = models.CharField(max_length=255)


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # 外來鍵,關聯關係寫在一對多中多的那一方
    publish = models.ForeignKey(to=Publish)
    authors = models.ManyToManyField(to=Author)

    def __str__(self):
        return self.name

注意事項:

1.id欄位不寫的話會自動新增
2.對於外來鍵欄位,Django會在欄位名上新增"_id"來建立資料庫中的列名
3.外來鍵欄位ForeignKey有一個null=True的設定,你可以賦給它空值None

二.新增表記錄

一對一:

# 方式一:
detail_obj = models.AuthorDetail.objects.filter(id=2).first()
models.Author.objects.create(name='Yven',sex=1,authordetail=detail_obj)

# 方式二:
models.Author.objects.create(name='hwt',sex=2,authordetail_id=1)

一對多:

# 方式一:
publish_obj = models.Publish.objects.filter(id=2).first()
models.Book.objects.create(name='水滸傳',price=24.5,publish=publish_obj)

# 方式二:
models.Book.objects.create(name='西遊記',price=24.5,publish_id=2)

多對多:

# 獲得書籍物件
book = models.Book.objects.create(name='水滸傳',price=24.5,publish_id=3)
# 獲得作者物件
yven = models.Author.objects.get(name='Yven')
hwt = models.Author.objects.get(name='hwt')

# 繫結多對多關係
# add中可以傳遞物件,可以傳遞id,也可以傳遞*列表如:(*[yven,hwt])
book.authors.add(yven,hwt)

#多對多關係其他常用API:
# 將某個特定的物件從被關聯物件集合中去除,可以傳遞物件,可以傳遞id,也可以傳遞*列表如:(*[yven,hwt])
book.authors.remove()
# 清空被關聯物件集合,無需傳參
book.authors.clear()
# 先清空再設定,傳遞的引數必須是可迭代物件,一般為列表,列表內可以是物件,也可以是id
book.authors.set()

三.基於物件的跨表查詢

一對一查詢

正向查詢(按欄位:authordetail)

# 查詢作者姓名為Yven的手機號
yven = models.Author.objects.get(name='Yven')
phone = yven.authordetail.phone

反向查詢(按表名小寫:author)

# 查詢手機號為12221321的作者名
authordetail = models.Author.objects.filter(phont='12221321').first()
name = authordetail.author.name

一對多查詢

正向查詢(按欄位:publish)

# 查詢西遊記的出版社名
book = models.Book.objects.filter(name='西遊記').first()
name = book.publish.name

反向查詢(按表名小寫_set.all():book_set.all())

# 查詢pk為2的出版社出版書籍的單價
publish = models.Publish.objects.filter(pk='2').first()
booklist = publish.book_set.all() #QuerySet物件
for obj in booklist:
    print(obj.price)

多對多查詢

正向查詢(按欄位.all():publish.all())

# 查詢水滸傳的所有作者
book = models.Book.objects.get(name='水滸傳')
author = book.authors.all()
for i in author:
    print(i.name)

反向查詢(按表名小寫_set.all():book_set.all())

# 查詢Yven寫的多少有書籍的單價
author = models.Author.objects.get(name='Yven')
book = author.book_set.all()
for i in book:
    print(i.price)

四.基於雙下劃線的跨表查詢

Django還提供了一種直觀而搞笑的方式在查詢(lookups)種表示關聯關係,它能自動確認SQL JOIN聯絡。要做跨關係查詢,就使用兩個下劃線來連線模型(model)間關聯欄位的名稱,知道最終連結到你想要的model為止。

一對一查詢

正向查詢(按欄位):authordetail

# 查詢Yven的地址
models.Author.objects.filter(name='Yven').values('authordetail__addr')

反向查詢(按表名):author

# 查詢Yven的地址
models.AuthorDetail.objects.filter(author__name='Yven').values('addr')

一對多查詢

正向查詢(按欄位):publish

# 查詢西遊記的出版社名
models.Book.objects.filter(name='西遊記').values('publish__name')

反向查詢(按表名):book

# 查詢西遊記的出版社名
models.Publish.objects.filter(book__name='西遊記').values('name')

多對多查詢

正向查詢(按欄位):authors

# 查詢水滸傳的作者性別
models.Book.objects.filter(name='水滸傳').values('authors__sex')

反向查詢(按表名):book

# 查詢水滸傳的作者性別
models.Author.objects.filter(book__name='水滸傳').values('sex')