django學習之Model(三)QuerySet

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   io   資料   

接下來主要學習Models中的Making queries

寫好models.py後,django會自動提供一個資料庫的抽象API,來實現CRUD(create, retrieve, update, delete)。這一部分主要就是怎樣去用這些API。在data model reference會有全部的講解。

接下來都會反覆用到下邊這個例子,或者在這段代碼上進行擴充:

from django.db import modelsclass Blog(models.Model):    name = models.CharField(max_length=100)    tagline = models.TextField()    # On Python 3: def __str__(self):    def __unicode__(self):        return self.nameclass Author(models.Model):    name = models.CharField(max_length=50)    email = models.EmailField()    # On Python 3: def __str__(self):    def __unicode__(self):        return self.nameclass Entry(models.Model):    blog = models.ForeignKey(Blog)    headline = models.CharField(max_length=255)    body_text = models.TextField()    pub_date = models.DateField()    mod_date = models.DateField()    authors = models.ManyToManyField(Author)    n_comments = models.IntegerField()    n_pingbacks = models.IntegerField()    rating = models.IntegerField()    # On Python 3: def __str__(self):    def __unicode__(self):        return self.headline

1-建立對象

一個model class 對應產生一個database table,一個class的執行個體就對應存進database table中的一個記錄。class中的field對應這table中的column.

調用python文法中的怎樣給類的對象賦值的文法,然後在調用對象的.save()函數,就建立了一條資料。

假設mysite/blog/models.py,下例:

>>> from blog.models import Blog>>> b = Blog(name=‘Beatles Blog‘, tagline=‘All the latest Beatles news.‘)>>> b.save()

 python文法中的賦值對應SQL的INSERT語句,只有調用save()的時候,django才對database進行了操作。並且save()沒有傳回值。如果把create和save用一條語句實現,create()方法可以實現。

2-儲存對資料的修改

也是用save()實現。即重新賦值,重新save:

>>> b5.name = ‘New name‘>>> b5.save()

 

這相當於SQL中的UPDATE, save()

3-儲存ForeignKey和ManyToManyField 的fields

update ForeignKey和update普通field是一樣的操作,從python角度來講,就是把一個object賦值給另一個類中的object類型的變數。

    blog = models.ForeignKey(Blog)#相當於blog是一個存放Blog的執行個體(對象)的一個變數。

 但是在update ManyToManyField的時候,用的是add()方法,且不用save()

>>> from blog.models import Author>>> joe = Author.objects.create(name="Joe")>>> entry.authors.add(joe)

 也可一進行大量操作:

>>> john = Author.objects.create(name="John")>>> paul = Author.objects.create(name="Paul")>>> george = Author.objects.create(name="George")>>> ringo = Author.objects.create(name="Ringo")>>> entry.authors.add(john, paul, george, ringo)

注意類型要匹配,不能把author add到blog中,這樣django會報錯。

4-檢索對象(Retrieving objects)

通過Manager來在model class上建立QuerySet (查詢)。QuerySet展示出database中的資料。filters可有可無,filters顧名思義,就是用來過濾,或者說篩選。在SQL中,QuerySet相當於SELECT語句,filters相當於WHERE或LIMIT。可以從model的Manager中獲得QuerySet,每個model都有一個Manager,預設使用的是objects.預設的是通過model class來實現,注意下面的代碼:

>>> Blog.objects<django.db.models.manager.Manager object at ...>>>> b = Blog(name=‘Foo‘, tagline=‘Bar‘)>>> b.objectsTraceback:    ...AttributeError: "Manager isn‘t accessible via Blog instances."

用的是Blog.objects, 而不是通常感覺上的對象的方法,因為manager是class的,而不是object的。官方文檔說,這種Manager的設計,加強了table-level與record-level操作的分離。可以理解為,整個django更好的實現了起架構的作用,就是不管具體的instance是啥樣的,而只注意在架構的設計上,讓其普遍適用於各種instance.

1)-最簡單的檢索database table的對象的方法,就是all,全檢索。在Manager上用all():

>>> all_entries = Entry.objects.all()

all()方法返回了一個QuerySet,包含database中所有的資料對象。

2)-稍微複雜點的就是加上filters來過濾出想要的結果。

常用的有2種:

a)-filter(**kwargs)   傳回值為滿足參數所表達的條件的QuerySet

b)-exclude(**kwargs)   傳回值QuerySet剔除了(exclude)參數所表達的條件的資料。

分別有如下2例:

Entry.objects.filter(pub_date__year=2006)#年代為2006年的被返回
Entry.objects.all().filter(pub_date__year=2006)#剔除2006年的,其他剩下的被返回

3)-鏈式filters

相當於級聯式的,看代碼就明白了:

>>> Entry.objects.filter(...     headline__startswith=‘What‘... ).exclude(...     pub_date__gte=datetime.date.today()... ).filter(...     pub_date__gte=datetime(2005, 1, 30)... )

4)-filter後的QuerySet是唯一且不變的

下面代碼中的q1,q2,q3是獨立互不影響的:

>>> q1 = Entry.objects.filter(headline__startswith="What")>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())>>> q3 = q1.filter(pub_date__gte=datetime.date.today())

5)-QuerySet很懶

直到你確實要用到值的時候,QuerySet才去database讀取資料,下面代碼中就是在print(q)的時候才讀database的:(具體解釋見When QuerySets are evaluated)

>>> q = Entry.objects.filter(headline__startswith="What")>>> q = q.filter(pub_date__lte=datetime.date.today())>>> q = q.exclude(body_text__icontains="food")>>> print(q)#hit the database

6)-可以用get方法檢索一個資料

>>> one_entry = Entry.objects.get(pk=1)

get()和filter()還是有區別的,如果沒有可以匹配的query,則get()會放回一個DoseNotExist的錯誤,這個exception是model class的一個參數。相似的,如果是有多個資料匹配get(),則會出現MultipleObjectReturned的錯誤。

7)-其他的QuerySet方法

完整的方法介紹在這裡QuerySet API Reference 

選前5個資料:

>>> Entry.objects.all()[:5]
>>> Entry.objects.all()[5:10]#從第6個到第10個

通常對QuerySet進行切片會返回一個新的QuerySet,有一個例外就是,如果用python中的step切片文法,就會對原QuerySet進行處理然後得到一個新的QuerySet:

>>> Entry.objects.all()[:10:2]

以下兩句是相同的:

>>> Entry.objects.order_by(‘headline‘)[0]>>> Entry.objects.order_by(‘headline‘)[0:1].get()

8)-Field lookups

在QuerySet的方法(filter,get,exclude)的參數列表中加入Field lookups作為限制條件:

>>> Entry.objects.filter(pub_date__lte=‘2006-01-01‘)

相當於SQL:

SELECT * FROM blog_entry WHERE pub_date <= ‘2006-01-01‘;

 思考:python能夠定義一個函數,是它接收正在運行計算中的變數,更多的理解移步python官網:Keyword Arguments 

一般在lookups中的都是用field名的,有一種情況例外,ForeignKey,可以在field名字後面加上 _id , 後面的值是這個外部model的id值:

>>> Entry.objects.filter(blog_id__exact=4)

若傳個不存在的關鍵字,lookup函數會產生TypeError的錯誤。

database API有很多lookup類型,完備的資料在這裡:field lookup reference. 下面來看一些常用的例子:

exact

>>> Entry.objects.get(headline__exact="Man bites dog")

相當於SQL

SELECT ... WHERE headline = ‘Man bites dog‘;

iexact

>>> Blog.objects.get(name__iexact="beatles blog")

SQL

SELECT ... WHERE headline LIKE ‘%Lennon%‘;

相似的還有icontains

還有startswith, endswith等方法,全部的方法得去這裡了field lookup reference.

9)-Lookups 能夠拓展relationships

django有一個強大且直觀的方法來處理資料的relationships,可以自動的協助你處理SQL中的JOINs操作。使用很簡單,只需要用跨model的相關的field的名稱,然後用雙底線 __來串連就行了。下例中是獲得所有的Entry的資料,條件是Entry中的Blog參數的名字是“Beatles Blog”:

>>> Entry.objects.filter(blog__name__exact=‘Beatles Blog‘)

這種span可以任意深的去關聯資料。也可以反向來用,例如從Blog中反向找entry:

>>> Blog.objects.filter(entry__headline__contains=‘Lennon‘)

如果要用filter去處理多個關係的時候,而且中間的某個model沒有滿足filter的條件,那麼,lookup不會報錯,而是會認為這個中間的model的field是空的(NULL值),但是是存在的。例如:

Blog.objects.filter(entry__authors__name=‘Lennon‘)

如果沒有author跟entry串連,lookup不會報錯,他會認為有一個空值的entry的。但是如果你明確指定了,如下:

Blog.objects.filter(entry__authors__name__isnull=True)

那就會返回這樣滿足條件的Blog了,說明他存在嘛。

如果你不想要這種結果,那就應該這樣寫:

1 Blog.objects.filter(entry__authors__isnull=False,          entry__authors__name__isnull=True)

注意以上兩種的區別,一個是不存在的,一個是確實存在而且想過濾掉某些幹擾資料的。

 

今天先到這兒!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.