1. 程式人生 > >Django資料操作

Django資料操作

出處:https://www.cnblogs.com/pemp/p/6066727.html

https://docs.djangoproject.com/en/1.10/ref/models/querysets/

1.一個模型類代表資料庫中的一個表,一個模型類的例項代表這個資料庫表中的一條特定的記錄。

2.管理器和查詢集。

  • 查詢集QuerySet表示從資料庫中取出來的物件的集合。它可以含有零個、一個或者多個過濾器。過濾器基於所給的引數限制查詢的結果。查詢集有可迭代和可切片的特點。
  • 每個模型都至少有一個管理器,它預設命名為objects。管理器只可以通過模型的類訪問,而不可以通過模型的例項訪問,目的是為了強制區分“表級別”的操作和“記錄級別”的操作。

1

2

3

4

5

6

7

>>>Blog.objects

<django.db.models.manager.Manager object at ...>

>>> b = Blog(name='Foo', tagline='Bar')

>>> b.objects

Traceback:

    ...

AttributeError: "Manager isn't accessible via Blog instances."

3.建立、更改,並儲存一個例項

1

2

3

from blog.models import Blog

= Blog(name='Beatles Blog', tagline='All the latest Beatles news.')

b.save() b.name = 'New name' b.save()

  注意:在呼叫b.save()時,Django才正真訪問資料庫。

  也可以使用管理器的create方法,一步建立和儲存。

1

= Person.objects.create(first_name="Bruce", last_name="Springsteen")

  • 更新ForeignKey 欄位的方式和儲存普通欄位相同 —— 只要把一個正確型別的物件賦值給該欄位。
  • 更新ManyToManyField 的方式有一些不同 —— 需要使用欄位的add()方法來增加關聯關係的一條記錄。為了在一條語句中,向ManyToManyField新增多條記錄,可以在呼叫add()方法時傳入多個引數

1

2

3

from blog.models import Author

joe = Author.objects.create(name="Joe")

entry.authors.add(joe)

  可以使用update() 方法為一個查詢集中所有物件的某個欄位都設定一個特定的值。

1

2

# Update all the headlines with pub_date in 2007.

Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

4.獲取物件(大多數情況下,需要從資料庫中查詢物件時,會使用all()、 get()、filter() 和exclude()。 然而,這只是冰山一角;查詢集方法的完整列表,請參見查詢集API 參考https://docs.djangoproject.com/en/1.10/ref/models/querysets/。)

  • 獲取所有物件

1

all_blogs = Blog.objects.all()

  all()方法返回包含資料庫中所有物件的一個查詢集。

  • 可以使用filter(**kwargs),exclude(**kwargs)設定過濾條件,返回一個新的查詢子集。

1

Entry.objects.filter(headline__startswith='What').exclude(pub_date__gte=datetime.date.today())

  • 每次篩選一個查詢集,得到的都是全新的另一個查詢集,它和之前的查詢集之間沒有任何繫結關係。每次篩選都會建立一個獨立的查詢集,它可以被儲存及反覆使用。如下:這三個查詢集都是獨立的。

1

2

3

>>> 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())

  • 查詢集 是惰性執行的 —— 建立查詢集不會帶來任何資料庫的訪問。直到查詢集需要求值時,Django 才會真正執行這個查詢。
  • 可以使用欄位查詢,指定欄位範圍,形式為field__lookuptype=value。(中間是兩個下劃線)。

1

2

3

4

Entry.objects.filter(pub_date__lte='2006-01-01')

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

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

Entry.objects.get(headline__contains='Lennon')

  大約有二十多種查詢的型別。查詢條件中指定的欄位必須是模型欄位的名稱。但有一個例外,對於ForeignKey你可以使用欄位名加上_id 字尾。

1

Entry.objects.filter(blog_id=4)

  • 多表關聯查詢:Django 提供一種強大而又直觀的方式來“處理”查詢中的關聯關係,只需使用關聯的模型欄位的名稱,並使用雙下劃線分隔。

1

2

3

4

5

6

7

8

9

10

11

12

13

#from django.db import models

 

#class Blog(models.Model):

#    name = models.CharField(max_length=100)

 

#class Author(models.Model):

#    name = models.CharField(max_length=50)

    

#class Entry(models.Model):

#    blog = models.ForeignKey(Blog)

#    authors = models.ManyToManyField(Author)

  

Entry.objects.filter(blog__name='Beatles Blog')

 這種跨越可以是任意的深度。它還可以反向工作。若要引用一個“反向”的關係,只需要使用該模型的小寫的名稱。

1

Blog.objects.filter(entry__headline__contains='Lennon')

  • 如果知道只有一個物件滿足你的查詢,可以使用管理器的get() 方法,它直接返回該物件:

1

one_blog = Blog.objects.get(pk=1)

  如果沒有結果滿足查詢,get() 將引發一個DoesNotExist 異常。類似地,如果有多條記錄滿足get() 的查詢條件,Django 也將報錯。這種情況將引發MultipleObjectsReturned異常。

  • 可以使用切片和索引限制查詢集。

1

2

3

4

5

#切片

Blog.objects.all()[5:10]

Blog.objects.all()[:10:2]

#索引

Blog.objects.order_by('headline')[0]

  通常,查詢集 的切片返回一個新的查詢集 —— 它不會執行查詢。有一個例外,是如果你使用Python 切片語法中"step"引數。

  • 其他常用的查詢API包括:
    • order_by:對查詢結果排序。
    • reverse:對查詢結果反向排序。
    • distinct:從返回結果中剔除重複記錄。
    • values:返回一個ValuesQuerySet —— QuerySet 的一個子類,迭代時返回字典而不是模型例項物件。
    • values_list:與values() 類似,只是在迭代時返回的是元組而不是字典。
    • count:返回在資料庫中對應的 QuerySet.物件的個數。
    • first,last,earliest,latest:返回QuerySet.物件的第一、最後、最早、最近的一條記錄。
    • exists:如果QuerySet 包含任何結果,則返回True,否則返回False。
  • 聚合函式和分組函式:
    • aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的識別符號,值是計算出來的聚合值。

1

2

3

>>> from django.db.models import Avg, MaxMin

>>> Book.objects.aggregate(average_price=Avg('price'), Max('price'), Min('price'))

{'average_price'34.35'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

    • 逐個物件的彙總結果可以由annotate()子句生成。當annotate()子句被指定之後,QuerySet中的每個物件都會被註上特定的值。與 aggregate() 不同的是, annotate() 不是一個終止子句。annotate()子句的返回結果是一個查詢集 (QuerySet);這個 QuerySet可以用任何QuerySet方法進行修改,包括 filter(), order_by(), 甚至是再次應用annotate()。

1

2

3

4

5

6

7

# Build an annotated queryset

>>> from django.db.models import Count

>>> q = Book.objects.annotate(num_authors=Count('authors'))

>>> q[0].num_authors

2

>>> q[1].num_authors

1

    • 在聚合函式中指定聚合欄位時,Django 允許你使用同樣的 雙下劃線 表示關聯關係;也同樣可以用關聯模型的小寫名稱和雙下劃線表示"反轉"關係。
  • 使用Q 物件進行復雜的查詢:Q 物件可以使用& 和| 操作符組合起來,可以使用~ 操作符取反,這允許組合正常的查詢和取反(NOT) 查詢。

1

2

3

4

Poll.objects.get(

    Q(question__startswith='Who'),

    Q(pub_date=date(200552)) | Q(pub_date=date(200556))

)

  • 比較物件:為了比較兩個模型例項,只需要使用標準的Python 比較操作符,即雙等於符號:==。在後臺,它會比較兩個模型主鍵的值。

 5.刪除物件

  delete()方法將立即刪除物件且沒有返回值。 

1

Entry.objects.filter(pub_date__year=2005).delete()

   注意,delete() 是唯一沒有在管理器 上暴露出來的查詢集方法。這是一個安全機制來防止你意外地請求Entry.objects.delete(),而刪除所有 的條目。如果你確實想刪除所有的物件,你必須明確地請求一個完全的查詢集:

1

Entry.objects.all().delete()

6.複製物件

  最簡單的方法是,只需要將pk 設定為None。 

1

2

3

4

5

blog = Blog(name='My blog', tagline='Blogging is easy')

blog.save() # blog.pk == 1

 

blog.pk = None

blog.save() # blog.pk == 2