1. 程式人生 > >Django Models 一對多,多對多,多對一關係解析

Django Models 一對多,多對多,多對一關係解析

1、資料型別    1)CharField 和TextField    2)EmailField, URLField 和IPAddressField    3)BooleanField 和NullBooleanField    4)FileField
2、類的關聯關係    classAuthor(models.Model):       name =models.CharField(max_length=100)    1)一對多關係       classBook(models.Model):          title =models.CharField(max_length=100)          author =models.ForeignKey("Author")       book= Book.objects.get(title="Django")      author = Book.author         #獲取該圖書的作者       books= author.book_set.all()
# 獲取該作者的所有圖書    2)多對多關係       classBook(models.Model):          title =models.CharField(max_length=100)          authors =models.ManyToManyField(Author)       book= Book.objects.get(title="Django")      authors = Book.author_set.all()  # 獲取該書的作者名單       books= author[2].book_set.all() # 獲取第三作者所著的所有圖書    3)多對多關係--通過第三個類       classBook(models.Model):          title =models.CharField(max_length=100)          authors =models.ManyToManyField(Author, through="Authoring")       classAuthoring(models.Model):         collaboration_type
=models.CharField(max_length=100)          book =models.ForeignKey(Book)          author =models.ForeignKey(Author)      chun_essay_compilations = Book.objects.filter(         author__name__endswith='Chun',         authoring__collaboration_type='essay'      )    4)帶約束的多對多關係       classBook(models.Model):          title =models.CharField(max_length=100)         authors = models.ManyToManyField(Author)        def __unicode__(self):
            returnself.title         class Meta:             abstract =True             ordering =['title']      classSmithBook(Book):         authors = models.ManyToManyField(Author,limit_choices_to={            'name__endswith': 'Smith'        }) 3、資料查詢   1)all      people =Person.objects.all().order_by('first')   2)filter      books_about_trees =Book.objects.filter(title__contains="Tree")       # SELECT *FROM myapp_book WHERE title LIKE "%Tree%"       john_does =Person.objects.filter(last="Doe", first="John")       # SELECT *FROM myapp_person WHERE last = "Doe" AND first = "John"       today =datetime.now()      overdue_books =book_queryset.filter(due_date__lt = today)   3)exclude   4)get   5)values     Person.objects.values('first')      # SELECT first FROMmyapp_person;      Person.objects.values_list('first')


Django 的 ORM 有多種關係:一對一,多對一,多對多。
各自定義的方式為 :        一對一: OneToOneField        多對一: ForeignKey        多對多: ManyToManyField 上邊的描述太過資料而缺乏人性化,我們來更人性化一些:        多個屬於一個,即 belong to :  ForeignKey,多個屬於一個        一個有一個,即 has one: OneToOneField        一個有很多個,即 has many:  lots of A belong to B 與 B has many A,在建立 ForeignKey 時,另一個表會自動建立對應的關係        一個既有很多個,又屬於很多個,即 has many and belong to : ManyToManyField,同樣只能在一個model類中說明,關聯表會自動建立。 訪問方式: 以下程式碼摘自 StackOverflow 用來說明訪問方式

Model Code

from django.db import models

classEngine(models.Model):
    name = models.CharField(max_length=25)def __unicode__(self):returnself.name

classCar(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)def __unicode__(self):returnself.name

classEngine2(models.Model):
    name = models.CharField(max_length=25)def __unicode__(self):returnself.name

classCar2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True)def __unicode__(self):returnself.name

OneToOneField Example

>>>from testapp.models importCar,Engine>>> c =Car.objects.get(name='Audi')>>> e =Engine.objects.get(name='Diesel')>>> e.car  #engine 的model 定義中並沒有car,這個是自動生成的,用關聯表的類名小寫直接訪問
<Car:Audi>  # 注意返回內容的不同

ForeignKey with unique=True Example

>>>from testapp.models importCar2,Engine2>>> c2 =Car2.objects.get(name='Mazda')>>> e2 =Engine2.objects.get(name='Wankel')>>> e2.car2_set.all()   # 在未定義的model中用關聯表類名小寫加"_set"來訪問,多對多也一樣[<Car2:Mazda>]   #注意返回內容的不同,這裡是一個QuerySet
以下內容摘自DjangoBook,僅供個人查詢使用:
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    def __unicode__(self):
        return self.name

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    def __unicode__(self):
        return self.title

如我們在第5章的講解,獲取資料庫物件的特定欄位的值只需直接使用屬性。 例如,要確定ID為50的書本的標題,我們這樣做:

>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'

但是,在之前有一件我們沒提及到的是表現為ForeignKey 或 ManyToManyField的關聯物件欄位,它們的作用稍有不同。

訪問外來鍵(Foreign Key)值

當你獲取一個ForeignKey 欄位時,你會得到相關的資料模型物件。 例如:

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

對於用`` ForeignKey`` 來定義的關係來說,在關係的另一端也能反向的追溯回來,只不過由於不對稱性的關係而稍有不同。 通過一個`` publisher`` 物件,直接獲取 books ,用 publisher.book_set.all() ,如下:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

實際上,book_set 只是一個 QuerySet(參考第5章的介紹),所以它可以像QuerySet一樣,能實現資料過濾和分切,例如:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]

屬性名稱book_set是由模型名稱的小寫(如book)加_set組成的。

訪問多對多值(Many-to-Many Values)

多對多和外來鍵工作方式相同,只不過我們處理的是QuerySet而不是模型例項。 例如,這裡是如何檢視書籍的作者:

>>> b = Book.objects.get(id=50)
>>> b.authors.all()
[<Author: Adrian Holovaty>, <Author: Jacob Kaplan-Moss>]
>>> b.authors.filter(first_name='Adrian')
[<Author: Adrian Holovaty>]
>>> b.authors.filter(first_name='Adam')
[]

反向查詢也可以。 要檢視一個作者的所有書籍,使用author.book_set ,就如這樣:

>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]

這裡,就像使用 ForeignKey欄位一樣,屬性名book_set是在資料模型(model)名後追加_set