django的Model instance reference


創建對象(Creating objects)

創建 model 的新實例和實例化其他的 Python 類一樣:

class  Model( **kwargs)

其中的關鍵字參數就是你在你的 model 中定義的字段的名稱。要注意實例化一個 model 並不會操作數據庫,要保存到數據庫的話,你需要使用 save() 方法。

保存對象(Saving objects)

要將對象保存至數據庫,就調用 save()

Model. save( [force_insert=Falseforce_update=False])

這個方法頗有些微妙之處,請查看下面幾節。

這部分是在 Django 1.0 中新增的: 請查看版本文檔

save() 方法的形式與之前的版本已經有所不同(加入了 force_insert 和 force_update 參數)。如果你要重寫該方法,就要留意這兩個參數。

自增主鍵(Auto-incrementing primary keys)

如果你的 model 有一個 AutoField 字段,它是一個自增主鍵,那么在你第一次調用 save() 方法時,就會計算得出這個自增主鍵的值,然后做為對象的一個屬性保存起來:

>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.') >>> b2.id # Returns None, because b doesn't have an ID yet. >>> b2.save() >>> b2.id # Returns the ID of your new object. 

在調用 save() 之前是拿不到 ID 值的,因為這個值是要靠數據庫來計算得出的,而非 Django。

(為使用方便,每個 model 默認都有一個 AutoField 自增字段,它的名稱是 id。不過你可以在某個字段上指定 primary_key=True,從而將這個字段變成主鍵字段。詳情請查看 AutoField

pk 屬性 (The pk property)

這部分是在 Django 1.0 中新增的: 請查看版本文檔
Model. pk

無論是你自己定義了主鍵,還是使用 Django 默認提供的主鍵,每個 model 都有一個指向主鍵的屬性,叫做 pk。它看上去只是是一個屬性,其實它是主鍵字段的一個別名。你可以象使用其他屬性一樣,獲取或是設置它的值,它會自動對主鍵字段的值進行更改。

顯式指定自增主鍵的值(Explicitly specifying auto-primary-key values)

如果一個 model 中含有一個 AutoField 自增字段,但是你在保存對象,並不想使用自動分配的 ID 值,而想顯示地定義新對象的 ID 值,那么只要在保存之時顯式的定義即可:

>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.') >>> b3.id # Returns 3. >>> b3.save() >>> b3.id # Returns 3. 

如果你手動指定了自增主鍵的值,請事先確認主鍵的值並未在數據庫中出現過;否則,如果你創建新對象時,顯式指定的自增主鍵的值,卻已存在於數據庫中,那么 Django 就不會認為你是想創建對象,而是認為你想更改某個已存在的記錄。

以上面所給的 'Cheddar Talk' 博客為例,下面的代碼將覆蓋數據庫中原來的記錄:

b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') b4.save() # Overrides the previous blog with ID=3! 

要了解為什么會覆蓋掉記錄,請查看下面的 Django 如何判斷是更新還是創建(How Django knows to UPDATE vs. INSERT) 一節。

如果你能確實主鍵值不發生沖突,那么對於大量保存對象而言,指定自增主鍵的值是非常有用的。

在保存對象時都發生了什么(What happens when you save?)

在你保存對象時,Django 會執行下面的步驟:

  1. 發出預保存信號(Emit a pre-save signal)。 發出 django.db.models.signals.pre_save 信號(signal),然后監聽該信號的函式就會執行某些定制操作。

  2. 預處理數據(Pre-process the data)。 對角中的每個字段都根據字段所需的數據格式,對數據自動進行調整。

    大多數字段是不需要預處理數據的,它們保持不變,只有那些有特殊行為的字段才需要預處理數據。例如,如果你的 model 中含有一個 DateField 字段,並且它指定了 auto_now=True,在預處理數據這個階段,就會修改該字段的數據,使其包含當前時間戳(我們的文檔還沒有將這些有“特殊行為”的字段完整地列出來)。

  3. 根據數據庫進行數據轉換(Prepare the data for the database)。 每個字段都要根據當前數據庫所要求的數據格式對當前值進行轉換。

    大多數字段無須轉換,它們多是簡單的數據類型,比如整數,字符串,都是隨時可寫的 Python 對象。但是,有更多的復雜數據類型需要對數據進行轉換和調整。

    例如,DateFields 字段使用的是一個 datetime 對象,這是一個 Python 類的實例,因為數據庫並不直接保存 datetime 對象,所以字段值必須被轉換成符合 ISO 標准的(ISO-compliant)的日期字符串,這樣數據庫才能識別。

  4. 將數據添加到數據庫中(Insert the data into the database)。 經過預處理和轉換的數據被組合成一條用以插入數據的 SQL 語句,從而完成對數據的添加。

  5. 發出已保存信號(Emit a post-save signal)。 發出 django.db.models.signals.post_save 信號,監聽該信號的函式們會執行某些既定的操作。

(Django 是如何判別更新還是創建的How Django knows to UPDATE vs. INSERT)

你可能已注意到,Django 的數據對象無論是創建對象還是保存修改過的對象,都是使用同樣的 save() 方法,因為 Django 已經對使用 INSERT 或 UPDATE SQL 語句的需求進行了抽象。因此,在你調用 save() 方法時,Django 會按照下列算法進行處理:

  • 如果對象的主鍵屬性是被賦與一個真值(True)時,(例如,即不是 None,也不是空字符串),Django 會執行一個 SELECT 查詢以判定與主鍵相綁定的記錄是否存在。
  • 如果該記錄存在,Django 就會執行另一個 UPDATE 查詢query。
  • 如果未設置對象的主鍵屬性,或者如果雖然設置了主鍵,但是與其綁定的記錄卻不存在,那么 Django 不會執行一個 INSERT 操作。

有一點要注意的是:如果你不能保證主鍵值並被用過,那么在保存新對象時,要注意不要顯式指定主鍵的值。想在這個細節上有更多了解,請查看上面的 顯示指定自增變量的值(Explicitly specifying auto-primary-key values) 和下面的 強制添加或更新(Forcing an INSERT or UPDATE) 。

強制新增或更新(Forcing an INSERT or UPDATE)

這部分是在 Django 1.0 中新增的: Please, see the release notes

在一些少見的場合中,運行 save() 方法時要求強制運行一條 SQL INSERT 語句,而非 UPDATE 語句。同理在某些情況下又強迫 UPDATE 而非 INSERT。在這種情況下,你可以通過設置 force_insert=True 或 force_update=True 參數的方式運行 save() 方法。同時提供兩個參數會拋開錯誤,因為 Django 不知道該 INSERT 還是 UPDATE

需要使用這兩個參數的用例是很少見的。一般來說,Django 的默認操作大多是正確的,如果使用了這兩個參數,如果出現錯誤,會使得調試跟蹤變得困難,所以這個特性僅適用於高級應用。

根據已存在的字段更新屬性(Updating attributes based on existing fields)

有些時候,你需要對某個字段做簡單的運算,比如對當前值遞增或遞減,可以用下面的方法達到這個目的:

>>> product = Product.objects.get(name='Venezuelan Beaver Cheese') >>> product.number_sold += 1 >>> product.save() 

從數據庫中得到舊的 number_sold 值是 10,然后再將 11 寫回到數據庫中。

根據某個字段進行賦值,要好於直接地顯式賦值。Django 提供了 F()表達式(F() expressions) 來解決根據字段賦值的問題。使用 F() 可以將上面的例子改寫為:

>>> from django.db.models import F >>> product = Product.objects.get(name='Venezuelan Beaver Cheese') >>> product.number_sold = F('number_sold') + 1 >>> product.save() 

這種方式並不是一開始就從數據庫中取出原始值,而是在執行 <>save()<> 操作的時候才根據取值字段從數據庫中取出原始值。

一旦對象被保存,你必須馬上重新得到對象,這樣才能得到你剛才得賦的字段值:

>>> product = Products.objects.get(pk=product.pk) >>> print product.number_sold 42 

詳情請查看 use in update queries 文檔中 F() expressions這一節

對象刪除(Deleting objects)

Model. delete()

對當前對象執行一條 DELETE SQL 語句。刪除操作僅僅作用於數據庫,Python 的實例對象依然存在,它所包含的字段同樣也存在。.

要了解更多細節,比如如何一次性刪除多個對象,請查看 對象刪除(Deleting objects).

其他的 model 實例方法(Other model instance methods)

有一部分方法有另外的特殊作用。

__str__

Model. __str__()

__str__() 是一個 Python 式的 "魔術方法" ,它定義了在你調用了對象的 str() 方法時,返回值的內容。Django 在很多場合使用 str(obj) (或是相關的其他的函式,比如下面提到的 unicode(obj)),最常見的就是在 Django 管理后台中做為對象的顯示值;或是用來在模板中顯示對象。因此,你應該總是為 __str__ 返回一個友好且易讀的字符串。這樣做雖然不是必須的,不過我們仍建議您這樣做。不過在您到處狂寫 __str__ 之前,請繼續閱讀下面所講的 __unicode__ 方法。

例如:

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) def __str__(self): # Note use of django.utils.encoding.smart_str() here because # first_name and last_name will be unicode strings. return smart_str('%s %s' % (self.first_name, self.last_name)) 

__unicode__

Model. __unicode__()

在你使用對象的 unicode() 方法時,就會調用 __unicode__() 。因為你的 model 中的字段從數據庫中得到的是 Unicode 字符串,所以一般情況下你要為你的 model 寫一個 __unicode__() 方法。上面的例子可以簡單地改寫為:

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) def __unicode__(self): return u'%s %s' % (self.first_name, self.last_name) 

如果你在 model 上只定義了 __unicode__() 方法卻並沒有定義 __str__() 方法,Django 將自動提供一個會在內部調用 __unicode__() 的 __str__() 方法,並且將返回值自動轉換成 UTF-8 字符串。對此,在開發時有如下建議:只定義 __unicode__() 方法,讓 Django 在必要時自動做字符串轉換。

get_absolute_url

Model. get_absolute_url()

定義 get_absolute_url() 方法會讓 Django 知道如何計算得到當前對象對應的網址 URL,例如:

def get_absolute_url(self): return "/people/%i/" % self.id 

Django 在管理后台使用該方法。如果某個對象定義了 get_absolute_url() 方法,在它的對象修改頁就會出現一個 "View on site" 鏈接,它會彈出一個與當前對象相關的網頁,網站就是 get_absolute_url() 返回的 URL

此外,Django 有些其他部分,也用到了 get_absolute_url() ,比如 RSS種子(syndication feed framework)。 get_absolute_url() 是一個對實際應用中很有用的快捷方法。

在模板中使用 get_absolute_url() 比直接在拼合網址要更好。例如,這種模板代碼就不是很好:

<a href="/people/{{ object.id }}/">{{ object.name }}</a>

但這種寫法就很好:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

注意

get_absolute_url() 返回的 URL 只能包含 ASCII 字符串 (這是 URI 的規則所要求的,詳見 RFC 2396) ,所以在必要的時候,會進行重編碼 URL-encoded,而在代碼和模板中 get_absolute_url() 時,會直接輸出結果而不會進行網址重編碼。如果你有大量的 Unicode 網址要進行重編碼,可以使用 django.utils.encoding.iri_to_uri() 函式來處理。

其他的實例方法(Extra instance methods)

除了 save()delete() 之外,一個 model 對象可能還有下列方法:

Model. get_FOO_display()

如果 model 有字段設置了 choices ,對象就會提供 get_FOO_display() 方法,這里的 FOO 就是字段的名稱。這個方法返回給用戶看的那個可讀性好的值,例如:

GENDER_CHOICES = ( ('M', 'Male'), ('F', 'Female'), ) class Person(models.Model): name = models.CharField(max_length=20) gender = models.CharField(max_length=1, choices=GENDER_CHOICES) 

...每個 Person 實例都有一個 get_gender_display() 方法。例如:

>>> p = Person(name='John', gender='M') >>> p.save() >>> p.gender 'M' >>> p.get_gender_display() 'Male' 
Model. get_next_by_FOO( **kwargs)
Model. get_previous_by_FOO( **kwargs)

如果 model 中的 DateField 字段和 DateTimeField 字段沒有設置 null=True,那么對象就會提供 get_next_by_FOO() 方法和 get_previous_by_FOO() 方法。這里的 FOO 就是時間字段的名稱。它根據當時時間字段的值返回下一個或是前一個對象。如果沒有找到就會拋開 DoesNotExist 異常。

這兩個方法的參數都是可選的,這些參數在 字段篩選條件(Field lookups) 中有詳細介紹。

要注意:如果在使用這兩個方法時遇到了相同的時間,那么它們就會將 ID 值做為第二條件,這樣才能保證記錄沒有重復或遺漏。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM