The Django Book

Appendix C: Database API Reference

闄勫綍C 鏁版嵁搴揂PI鍙傝

Djangos database API is the other half of the model API discussed in Appendix B. Once youve defined a model, youll use this API any time you need to access the database. Youve seen examples of this API in use throughout the book; this appendix explains all the various options in detail.

Django鏁版嵁搴揂PI鏄檮褰旴涓璁鸿繃鐨勬暟鎹ā鍨婣PI鐨勫彟涓閮ㄥ垎銆備竴鏃﹀畾涔変簡鏁版嵁妯″瀷锛屼綘灏嗕細鍦ㄤ换浣曡璁块棶鏁版嵁搴撶殑鏃跺欎娇鐢ㄦ暟鎹簱API銆備綘宸茬粡鍦ㄦ湰涔︿腑鐪嬪埌浜嗗緢澶氭暟鎹簱API鐨勪緥瀛愶紝杩欑瘒闄勫綍瀵规暟鎹簱API鐨勫悇绉嶅彉鍖栬鍔犻槓閲娿

Like the model APIs discussed in Appendix B, though these APIs are considered very stable, the Django developers consistently add new shortcuts and conveniences. Its a good idea to always check the latest documentation online, available at http://www.djangoproject.com/documentation/0.96/db-api/.

鍜岄檮褰旴涓璁虹殑鏁版嵁妯″瀷API鏃朵竴鏍凤紝灏界璁や负杩欎簺API宸茬粡寰堢ǔ瀹氾紝Django寮鍙戣呬竴鐩村湪澧炲姞鍚勭渚挎嵎鏂规硶銆傚洜姝わ紝鏌ョ湅鏈鏂扮殑鍦ㄧ嚎鏂囨。鏄釜濂芥柟娉曪紝鍦ㄧ嚎鏂囨。鍙互鍦 http://www.djangoproject.com/documentation/0.96/db-api/ 鎵惧埌.

Throughout this reference, well refer to the following models, which might form a simple Weblog application:

璐┛杩欎釜鍙傝冩枃妗o紝鎴戜滑閮戒細鎻愬埌涓嬮潰鐨勮繖涓猰odels銆傚畠鎴栬鏉ヨ嚜浜庝竴涓畝鍗曠殑鍗氬绋嬪簭銆

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateTimeField()
    authors = models.ManyToManyField(Author)

    def __str__(self):
        return self.headline

Creating Objects

鍒涘缓瀵硅薄

To create an object, instantiate it using keyword arguments to the model class, and then call save() to save it to the database:

瑕佸垱寤轰竴涓璞, 鐢ㄦā鍨嬬被浣跨敤鍏抽敭瀛楀弬鏁板疄渚嬪寲瀹, 鎺ョ潃璋冪敤 save() 灏嗗畠淇濆瓨鍒版暟鎹簱涓:

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

This performs an INSERT SQL statement behind the scenes. Django doesnt hit the database until you explicitly call save() .

杩欎細鍦ㄥ悗鍙版墽琛屼竴涓猄QL璇彞. 濡傛灉鎮ㄤ笉鏄惧紡鍦拌皟鐢 save() , Django涓嶄細淇濆瓨鍒版暟鎹簱.

The save() method has no return value.

save() 鏂规硶娌℃湁杩斿洖鍊.

To create an object and save it all in one step see the create manager method discussed shortly.

瑕佸湪涓涓楠や腑鍒涘缓骞朵繚瀛樹竴涓璞, 鍙傝浼氱◢鍚庤璁虹殑 create 绠$悊鑰呮柟娉,

What Happens When You Save?

褰撴偍淇濆瓨鐨勬椂鍊欏彂鐢熶簡浠涔?

When you save an object, Django performs the following steps:

褰撴偍淇濆瓨涓涓璞$殑鏃跺, Django鎵ц涓嬮潰鐨勬楠:

Emit a pre_save signal. This provides a notification that an object is about to be saved. You can register a listener that will be invoked whenever this signal is emitted. These signals are still in development and werent documented when this book went to press; check the online documentation for the latest information.

鍙戝嚭涓涓瀛樹俊鍙枫 瀹冨彂鍑轰竴涓皢瑕佸瓨鍌ㄤ竴涓璞$殑閫氱煡銆備綘鍙互娉ㄥ唽涓涓洃鍚▼搴忥紝鍦ㄤ俊鍙峰彂鍑虹殑鏃跺欏氨浼氳璋冪敤銆傚埌鏈功鍑虹増鏃讹紝杩欎簺淇″彿浠嶅湪寮鍙戜腑骞朵笖娌℃湁鏂囨。鍖栵紝璇锋煡鐪嬪湪绾挎枃妗f潵鑾峰緱鏈鏂扮殑娑堟伅銆

Preprocess the data. Each field on the object is asked to perform any automated data modification that the field may need to perform.

棰勫鐞嗘暟鎹. 瀵逛簬瀵硅薄鐨勬瘡涓瓧娈碉紝灏嗘牴鎹渶瑕佽繘琛岃嚜鍔ㄧ殑鏁版嵁淇敼銆

Most fields do no preprocessing the field data is kept as is. Preprocessing is only used on fields that have special behavior, like file fields.

澶ч儴鍒嗗瓧娈靛苟涓嶉澶勭悊锛屽畠浠細淇濇寔瀹冧滑鍘熸潵鐨勬牱瀛愩傞澶勭悊浠呬粎鐢ㄥ湪閭d簺鏈夌壒娈婃ц川鐨勫瓧娈碉紝姣斿鏂囦欢瀛楁銆

Prepare the data for the database. Each field is asked to provide its current value in a data type that can be written to the database.

涓烘暟鎹簱鍑嗗鏁版嵁銆 姣忎竴涓瓧娈靛厛瑕佹妸褰撳墠鍊艰浆鍖栨垚鏁版嵁搴撲腑鍙互淇濆瓨鐨勬暟鎹殑绫诲瀷銆

Most fields require no data preparation. Simple data types, such as integers and strings, are ready to write as a Python object. However, more complex data types often require some modification. For example, DateFields use a Python datetime object to store data. Databases dont store datetime objects, so the field value must be converted into an ISO-compliant date string for insertion into the database.

澶у鏁板瓧娈电殑鏁版嵁涓嶉渶瑕侀鍏堝噯澶囥傜畝鍗曠殑鏁版嵁绫诲瀷锛屾瘮濡傛暣鍨嬪拰瀛楃涓茬瓑python瀵硅薄鍙互鐩存帴鍐欒繘鏁版嵁搴撱傜劧鑰岋紝鏇村鏉傜殑鏁版嵁绫诲瀷闇瑕佸仛涓浜涗慨鏀广傛瘮濡傦紝 DateFields 浣跨敤python鐨 datetime 瀵硅薄鏉ュ瓨鍌ㄦ暟鎹傛暟鎹簱骞朵笉鑳藉瓨鍌 datetime 瀵硅薄锛屾墍浠ヨ瀛楁瑕佸瓨鍏ユ暟鎹簱鍏堣鎶婂艰浆鍖栦负绗﹀悎ISO鏍囧噯鐨勬棩鏈熷瓧绗︿覆銆

Insert the data into the database. The preprocessed, prepared data is then composed into an SQL statement for insertion into the database.

鍚戞暟鎹簱涓彃鍏ユ暟鎹 缁忚繃棰勫鐞嗗噯澶囧ソ鐨勬暟鎹劧鍚庝細缁勫悎鎴愪竴鏉QL璇彞鏉ユ彃鍏ユ暟鎹簱銆

Emit a post_save signal. As with the pre_save signal, this is used to provide notification that an object has been successfully saved. Again, these signals are not yet documented.

鍙戝嚭瀛樻瘯淇″彿銆 涓庨瀛樹俊鍙风被浼硷紝瀛樻瘯淇″彿鍦ㄥ璞℃垚鍔熶繚瀛樹箣鍚庡彂鍑恒傚悓鏍凤紝杩欎簺淇″彿涔熻繕娌℃湁鏂囨。鍖栥

Autoincrementing Primary Keys

鑷涓婚敭

For convenience, each model is given an autoincrementing primary key field named id unless you explicitly specify primary_key=True on a field (see the section titled AutoField in Appendix B).

涓轰簡鏂逛究锛屾瘡涓暟鎹簱妯″瀷閮戒細娣诲姞涓涓嚜澧炰富閿瓧娈碉紝鍗 id 銆傞櫎闈炰綘鍦ㄦ煇涓瓧娈靛睘鎬т腑鏄惧紡鐨勬寚瀹 primary_key=True 锛堝弬瑙侀檮褰旴涓涓篈utoField鐨勭珷鑺傦級銆

If your model has an AutoField , that autoincremented value will be calculated and saved as an attribute on your object the first time you call save() :

濡傛灉浣犵殑鏁版嵁搴撴ā鍨嬩腑鍖呮嫭 AutoField 锛岃繖涓嚜澧為噺鐨勫煎皢浼氬湪浣犵涓娆¤皟鐢 save() 鏃朵綔涓哄璞$殑涓涓睘鎬ц绠楀緱鍑哄苟淇濆瓨璧锋潵銆

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

>>> b2.save()
>>> b2.id     # Returns the ID of your new object.
14

Theres no way to tell what the value of an ID will be before you call save() , because that value is calculated by your database, not by Django.

鍦ㄨ皟鐢 save() 鏂规硶涔嬪墠娌℃湁鍔炴硶鐭ラ亾ID鐨勫硷紝鍥犱负杩欎釜鍊兼槸鏁版嵁搴撹绠楀嚭鏉ョ殑锛屼笉鏄疍jango銆

If a model has an AutoField but you want to define a new objects ID explicitly when saving, just define it explicitly before saving, rather than relying on the autoassignment of the ID:

濡傛灉浣犳兂鍦ㄤ竴涓柊鏁版嵁瀛樺偍鏃讹紝瀹氫箟鍏 AutoField 瀛楁鍊硷紝鑰屼笉渚濊禆浜庢暟鎹簱鑷姩鍒嗛厤锛屾槑纭祴鍊煎嵆鍙

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

If you assign auto-primary-key values manually, make sure not to use an already existing primary key value! If you create a new object with an explicit primary key value that already exists in the database, Django will assume youre changing the existing record rather than creating a new one.

濡傛灉浣犳墜鍔ㄦ寚瀹氳嚜澧炰富閿殑鍊硷紝瑕佺‘淇濊繖涓富閿湪鏁版嵁搴撲腑涓嶅瓨鍦紒濡傛灉浣犳樉寮忓湴鎸囧畾涓婚敭鏉ュ垱寤烘柊瀵硅薄锛岃岃繖涓富閿湪鏁版嵁搴撲腑宸茬粡瀛樺湪鐨勮瘽锛孌jango浼氳涓轰綘瑕佹洿鏀瑰凡缁忓瓨鍦ㄧ殑閭f潯璁板綍锛岃屼笉鏄垱寤轰竴涓柊鐨勩

Given the preceding 'Cheddar Talk' blog example, this example would override the previous record in the database:

浠ュ墠闈㈢殑 'Cheddar Talk' blog涓轰緥锛屼笅闈㈢殑渚嬪瓙浼氳鐩栨暟鎹簱涓凡缁忓瓨鍦ㄧ殑璁板綍锛

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

Explicitly specifying auto-primary-key values is mostly useful for bulk-saving objects, when youre confident you wont have primary key collision.

濡傛灉浣犵‘淇′笉浼氫骇鐢熶富閿啿绐佺殑璇濓紝褰撻渶瑕佷繚瀛樺ぇ閲忓璞$殑鏃跺欙紝鏄庣‘鎸囧畾鑷涓婚敭鐨勫兼槸闈炲父鏈夌敤鐨勩

Saving Changes to Objects

淇濆瓨瀵瑰璞″仛鐨勪慨鏀

To save changes to an object thats already in the database, use save() .

瑕佷繚瀛樹竴涓凡缁忓湪鏁版嵁搴撲腑瀛樺湪鐨勫璞$殑鍙樻洿, 浣跨敤 save() .

Given a Blog instance b5 that has already been saved to the database, this example changes its name and updates its record in the database:

鍋囧畾 b5 杩欎釜 Blog 瀹炰緥宸茬粡淇濆瓨鍒版暟鎹簱涓紝涓嬮潰杩欎釜渚嬪瓙鏇存敼浜嗗畠鐨勫悕瀛楋紝骞朵笖鏇存柊浜嗗畠鍦ㄦ暟鎹簱涓殑璁板綍锛

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

This performs an UPDATE SQL statement behind the scenes. Again, Django doesnt hit the database until you explicitly call save() .

杩欎釜渚嬪瓙鍦ㄥ悗鍙版墽琛屼簡 UPDATE 杩欎竴SQL璇彞銆傚啀娆″0鏄庯紝Django鍦ㄤ綘鏄惧紡鍦拌皟鐢 save() 涔嬪墠鏄笉浼氭洿鏂版暟鎹簱鐨勩

How Django Knows When to UPDATE and When to INSERT

Django濡備綍寰楃煡浣曟椂 UPDATE 锛屼綍鏃 INSERT

You may have noticed that Django database objects use the same save() method for creating and changing objects. Django abstracts the need to use INSERT or UPDATE SQL statements. Specifically, when you call save() , Django follows this algorithm:

浣犲彲鑳藉凡缁忔敞鎰忓埌Django鏁版嵁搴撳璞″湪鍒涘缓鍜屾洿鏀瑰璞℃椂锛屼娇鐢ㄤ簡鍚屼竴涓 save() 鍑芥暟銆侱jango鎶借薄鍖栦簡瀵筍QL璇彞涓殑 INSERTUPDATE 鐨勯渶姹傦紝褰撲綘璋冪敤 save() 鐨勬椂鍊欙紝Django浼氶伒瀹堜笅闈㈢殑鍘熷垯锛

  • If the objects primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes a SELECT query to determine whether a record with the given primary key already exists.

  • 濡傛灉瀵硅薄鐨勪富閿睘鎬ц璁剧疆鎴愮浉褰撲簬 True 鐨勫硷紙姣斿 None 鎴栬呯┖瀛楃涓蹭箣澶栫殑鍊硷級锛孌jango浼氭墽琛屼竴涓 SELECT 鏌ヨ鏉ユ娴嬫槸鍚﹀凡瀛樺湪涓涓浉鍚屼富閿殑璁板綍銆

  • If the record with the given primary key does already exist, Django executes an UPDATE query.

  • 濡傛灉宸茬粡瀛樺湪涓涓富閿浉鍚岀殑璁板綍锛孌jango灏辨墽琛 UPDATE 鏌ヨ銆

  • If the objects primary key attribute is not set, or if its set but a record doesnt exist, Django executes an INSERT .

  • 濡傛灉瀵硅薄鐨勪富閿睘鎬 娌℃湁 琚缃紝鎴栬呰璁剧疆浣嗘暟鎹簱涓病鏈変笌涔嬪悓涓婚敭鐨勮褰曪紝閭d箞Django灏变細鎵ц INSERT 鏌ヨ銆

Because of this, you should be careful not to specify a primary key value explicitly when saving new objects if you cannot guarantee the primary key value is unused.

姝e洜濡傛锛屽鏋滀綘涓嶈兘纭俊鏁版嵁搴撲腑涓嶅瓨鍦ㄤ富閿浉鍚岀殑璁板綍鐨勮瘽锛屼綘搴旇閬垮厤娌℃湁鏄庣‘鎸囧畾涓婚敭鐨勫笺

Updating ForeignKey fields works exactly the same way; simply assign an object of the right type to the field in question:

鏇存柊 ForeignKey 瀛楁鍘熺悊鏄竴鏍风殑锛屽彧鏄缁欒繖涓瓧娈佃祴浜堟纭被鍨嬬殑瀵硅薄灏辫浜嗐

>>> joe = Author.objects.create(name="Joe")
>>> entry.author = joe
>>> entry.save()

Django will complain if you try to assign an object of the wrong type.

濡傛灉浣犳妸涓涓敊璇被鍨嬬殑瀵硅薄璧嬬粰瀹冿紝Django浼氳鎶ョ殑銆

Retrieving Objects

鑾峰彇瀵硅薄

Throughout the book youve seen objects retrieved using code like the following:

鍦ㄨ繖鏈功涓紝鑾峰彇瀵硅薄閮戒娇鐢ㄤ笅闈㈣繖鏍风殑浠g爜瀹炵幇鐨勶細

>>> blogs = Blog.objects.filter(author__name__contains="Joe")

There are quite a few moving parts behind the scenes here: when you retrieve objects from the database, youre actually constructing a QuerySet using the models Manager . This QuerySet knows how to execute SQL and return the requested objects.

鍦ㄨ繖骞曞悗浼氭湁鐩稿綋澶氱殑姝ラ锛氬綋浣犱粠鏁版嵁搴撲腑鑾峰彇瀵硅薄鐨勬椂鍊欙紝浣犲疄闄呬笂鐢 Manager 妯″潡鏋勯犱簡涓涓 QuerySet 锛岃繖涓 QuerySet 鐭ラ亾鎬庢牱鍘绘墽琛孲QL璇彞骞惰繑鍥炰綘鎯宠鐨勫璞°

Appendix B looked at both of these objects from a model-definition point of view; now well look at how they operate.

闄勫綍B浠庢ā鍧楀畾涔夌殑瑙掑害璁ㄨ浜嗚繖涓や釜瀵硅薄锛岀幇鍦ㄨ鎴戜滑鐮旂┒涓涓嬪畠浠槸鎬庝箞宸ヤ綔鐨勩

A QuerySet represents a collection of objects from your database. It can have zero, one, or many filters criteria that narrow down the collection based on given parameters. In SQL terms, a QuerySet equates to a SELECT statement, and a filter is a limiting clause such as WHERE or LIMIT .

QuerySet 浠h〃浜嗕綘鐨勬暟鎹簱涓殑瀵硅薄鐨勪竴涓泦鍚堛傚畠鏍规嵁鎵缁欏弬鏁板彲浠ユ瀯閫犺嫢骞蹭釜 杩囨护鍣 鏉ョ缉灏忚繖涓泦鍚堢殑瑙勬ā銆傜敤SQL鏈鏉ヨ锛屼竴涓 QuerySet 灏辩浉褰撲簬涓涓 SELECT 璇彞锛岃繃婊ゅ櫒鐩稿綋浜庤濡 WHERE 鎴栬 LIMIT 鐨勯檺瀹氳銆

You get a QuerySet by using your models Manager . Each model has at least one Manager , and its called objects by default. Access it directly via the model class, like so:

浣犻氳繃妯″潡鐨 Manager 灏卞彲浠ュ緱鍒颁竴涓 QuerySet 銆傛瘡涓ā鍧楄嚦灏戞湁涓涓 Manager 锛岄粯璁ゅ悕绉版槸 objects 銆傚彲浠ラ氳繃妯″潡绫绘潵鐩存帴璁块棶瀹冿紝姣斿锛

>>> Blog.objects
<django.db.models.manager.Manager object at 0x137d00d>

Manager s are accessible only via model classes, rather than from model instances, to enforce a separation between table-level operations and record-level operations:

涓轰簡寮哄埗鍒嗙鏁版嵁琛ㄧ骇鍒殑鎿嶄綔鍜屾暟鎹褰曠骇鍒殑鎿嶄綔锛 Manager 鍙兘閫氳繃妯″潡绫昏屼笉鏄ā鍧楀疄渚嬫潵璁块棶锛

>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Manager isn't accessible via Blog instances.

The Manager is the main source of QuerySets for a model. It acts as a root QuerySet that describes all objects in the models database table. For example, Blog.objects is the initial QuerySet that contains all Blog objects in the database.

瀵逛竴涓ā鍧楁潵璁诧紝 ManagerQuerySets 鐨勪富瑕佹潵婧愩傚畠灏卞儚涓涓牴鏈殑 QuerySet 锛屽彲浠ュ妯″潡鐨勬暟鎹簱琛ㄤ腑鐨勬墍鏈夊璞¤繘琛屾弿杩般傛瘮濡傦紝 Blog.objects 灏辨槸鍖呭惈鐫鏁版嵁搴撲腑鎵鏈夌殑 Blog 瀵硅薄鐨勪竴涓牴鏈殑 QuerySet

Caching and QuerySets

缂撳瓨涓庢煡璇㈤泦

Each QuerySet contains a cache, to minimize database access. Its important to understand how it works, in order to write the most efficient code.

涓轰簡鍑忓皯鏁版嵁搴撹闂鏁帮紝姣忎釜 QuerySet 鍖呭惈涓涓紦瀛橈紝瑕佸啓鍑洪珮鏁堢殑浠g爜锛岀悊瑙h繖涓鐐瑰緢閲嶈銆

In a newly created QuerySet , the cache is empty. The first time a QuerySet is evaluated and, hence, a database query happens Django saves the query results in the QuerySet s cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet is being iterated over). Subsequent evaluations of the QuerySet reuse the cached results.

鍦ㄥ垰琚垱寤虹殑 QuerySet 涓紝缂撳瓨鏄┖鐨勩傚綋 QuerySet 绗竴娆¤璧嬪硷紝灏辨槸鎵ц鏁版嵁搴撴煡璇㈢殑鏃跺欙紝Django浼氭妸鏌ヨ缁撴灉淇濆瓨鍒拌繖涓 QuerySet 鐨勭紦瀛樹腑锛屽苟杩斿洖璇锋眰缁撴灉锛堜緥濡傦紝 QuerySet 杩唬缁撴潫鐨勬椂鍊欙紝灏变細杩斿洖涓嬩竴鏉¤褰曪級銆傚啀娆′娇鐢 QuerySet 鐨勫肩殑璇濅細閲嶅浣跨敤缂撳瓨涓殑鍐呭銆

Keep this caching behavior in mind, because it may bite you if you dont use your QuerySet``s correctly. For example, the following will create two ``QuerySet s, evaluate them, and throw them away:

瑕佹椂鍒昏浣忚繖绉嶇紦瀛樻満鍒讹紝鍥犱负濡傛灉浣犱笉姝g‘鐨勪娇鐢 QuerySet 鐨勮瘽锛屽彲鑳戒細閬囧埌楹荤儲銆備緥濡傦紝涓嬮潰杩欐浠g爜浼氬垎鍒骇鐢熶袱涓 QuerySet 锛岃绠楀嚭鏉ョ劧鍚庝涪寮冦

print [e.headline for e in Entry.objects.all()]
print [e.pub_date for e in Entry.objects.all()]

That means the same database query will be executed twice, effectively doubling your database load. Also, theres a possibility the two lists may not include the same database records, because an Entry may have been added or deleted in the split second between the two requests.

杩欏氨鎰忓懗鐫鐩稿悓鐨勬暟鎹簱鐨勬煡璇細琚墽琛屼袱娆★紝浣挎暟鎹簱鐨勮礋杞藉姞鍊嶃傝屼笖杩欎袱涓垪琛ㄥ寘鍚殑鏁版嵁鍙兘涓嶅悓锛屽洜涓哄湪涓ゆ鏌ヨ鐨勯棿闅欙紝鍙兘鏈変竴涓 Entry 琚坊鍔犳垨鏄垹闄や簡銆

To avoid this problem, simply save the QuerySet and reuse it:

閬垮厤杩欎釜闂锛岀畝鍗曠殑鏂规硶鏄繚瀛樿繖涓 QuerySet 骞朵笖閲嶇敤瀹冦

queryset = Poll.objects.all()
print [p.headline for p in queryset] # Evaluate the query set.
print [p.pub_date for p in queryset] # Reuse the cache from the evaluation.

Filtering Objects

杩囨护鍣ㄥ璞

The simplest way to retrieve objects from a table is to get all of them. To do this, use the all() method on a Manager :

浠庢暟鎹〃涓幏鍙栧璞$殑鏈绠鍗曠殑鏂规硶灏辨槸寰楀埌鎵鏈夌殑瀵硅薄锛屽氨鏄皟鐢ㄤ竴涓 Managerall() 鏂规硶銆

>>> Entry.objects.all()

The all() method returns a QuerySet of all the objects in the database.

all() 鏂规硶杩斿洖涓涓寘鍚暟鎹簱鐨勬墍鏈夊璞$殑 QuerySet

Usually, though, youll need to select only a subset of the complete set of objects. To create such a subset, you refine the initial QuerySet , adding filter conditions. Youll usually do this using the filter() and/or exclude() methods:

浣嗘槸閫氬父鎯呭喌涓嬶紝鍙渶瑕佷粠鎵鏈夊璞′腑璇锋眰涓涓瓙闆嗭紝杩欏氨闇瑕佷綘缁嗗寲涓涓嬪垰鎵嶇殑 QuerySet 锛屽姞涓浜涜繃婊ゆ潯浠躲傜敤 filter()exclude() 鏂规硶鍙互瀹炵幇杩欐牱鐨勫姛鑳斤細

>>> y2006 = Entry.objects.filter(pub_date__year=2006)
>>> not2006 = Entry.objects.exclude(pub_date__year=2006)

filter() and exclude() both take field lookup arguments, which are discussed in detail shortly.

filter()exclude() 鏂规硶閮芥帴鍙 瀛楁鏌ヨ 鍙傛暟锛屾垜浠◢鍚庝細璇︾粏璁ㄨ銆

Chaining Filters

绾ц仈杩囨护鍣

The result of refining a QuerySet is itself a QuerySet , so its possible to chain refinements together, for example:

缁嗗寲杩囩殑 QuerySet 鏈韩灏辨槸涓涓 QuerySet 锛屾墍浠ュ彲浠ヨ繘涓姝ョ粏鍖栵紝姣斿锛

>>> qs = Entry.objects.filter(headline__startswith='What')
>>> qs = qs..exclude(pub_date__gte=datetime.datetime.now())
>>> qs = qs.filter(pub_date__gte=datetime.datetime(2005, 1, 1))

This takes the initial QuerySet of all entries in the database, adds a filter, then an exclusion, and then another filter. The final result is a QuerySet containing all entries with a headline that starts with What that were published between January 1, 2005, and the current day.

杩欐牱锛屾垜浠妸鏈鍒濊繃鐨勬暟鎹簱涓墍鏈夊唴瀹圭殑涓涓 QuerySet 缁忚繃娣诲姞涓涓繃婊ゅ櫒銆佷竴涓弽鍚戣繃婊ゅ櫒鍜屽彟澶栦竴涓繃婊ゅ櫒锛屽緱鍒颁竴涓渶缁堢殑 QuerySet 锛屾渶缁堢粨鏋滀腑鍖呭惈浜嗘墍鏈夋爣棰樹互鈥淲hat鈥濆紑澶寸殑2005骞磋嚦浠婄殑鍑虹増鐨勬潯鐩

Its important to point out here that QuerySets are lazy the act of creating a QuerySet doesnt involve any database activity. In fact, the three preceding lines dont make any database calls; you can chain filters together all day long and Django wont actually run the query until the QuerySet is evaluated .

杩欓噷闇瑕佹寚鍑虹殑涓鐐规槸锛屽垱寤轰竴涓 QuerySet 骞朵笉浼氱壍娑夊埌浠讳綍鏁版嵁搴撳姩浣溿備簨瀹炰笂锛屼笂闈㈢殑涓夎骞朵笉浼氫骇鐢 浠讳綍鐨 鏁版嵁搴撹皟鐢ㄣ傚氨鏄浣犲彲浠ヨ繛鎺ヤ换鎰忓涓繃婊ゅ櫒锛屽彧瑕佷綘涓嶆妸杩欎釜 QuerySet 鐢ㄤ簬璧嬪肩殑璇濓紝Django鏄笉浼氭墽琛屾煡璇㈢殑銆

You can evaluate a QuerySet in any following ways:

浣犲彲浠ョ敤涓嬮潰鐨勬柟娉曟潵璁$畻 QuerySet 鐨勫硷細

Iterating : A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, the following QuerySet isnt evaluated until its iterated over in the for loop:

杩唬QuerySet 鏄彲浠ヨ凯浠g殑锛屽畠浼氬湪杩唬缁撴潫鐨勬椂鍊欐墽琛屾暟鎹簱鏌ヨ銆備緥濡傦紝涓嬮潰鐨勮繖涓 QuerySet 鍦╢or寰幆杩唬瀹屾瘯涔嬪墠锛屾槸涓嶄細琚祴鍊肩殑锛

qs = Entry.objects.filter(pub_date__year=2006)
qs = qs.filter(headline__icontains="bill")
for e in qs:
    print e.headline

This prints all headlines from 2006 that contain bill but causes only one database hit.

瀹冧細鎵撳嵃2006骞存墍鏈夊寘鍚玝ill鐨勬爣棰橈紝浣嗗彧浼氳Е鍙戜竴娆℃暟鎹簱璁块棶銆

Printing it : A QuerySet is evaluated when you call repr() on it. This is for convenience in the Python interactive interpreter, so you can immediately see your results when using the API interactively.

鎵撳嵃 锛氬 QuerySet 浣跨敤 repr() 鏂规硶鏃讹紝瀹冩槸浼氳璧嬪肩殑銆傝繖鏄负浜嗘柟渚縋ython鐨勪氦浜掕В閲婂櫒锛岃繖鏍峰湪浜や簰鐜涓娇鐢ˋPI鏃跺氨浼氱珛鍒荤湅鍒扮粨鏋溿

Slicing : As explained in the upcoming Limiting QuerySets section, a QuerySet can be sliced using Pythons array-slicing syntax. Usually slicing a QuerySet returns another (unevaluated)``QuerySet``, but Django will execute the database query if you use the step parameter of slice syntax.

鍒囩墖 锛 鍦ㄦ帴涓嬫潵鐨勨滈檺閲忔煡璇㈤泦鈥濅竴鑺備腑灏变細瑙i噴杩欎竴鐐癸紝 QuerySet 鏄彲浠ョ敤Python鐨勬暟缁勫垏鐗囩殑璇硶鏉ュ垏鐗囩殑銆傞氬父鍒囩墖杩囩殑 QuerySet 浼氳繑鍥炲彟澶栦竴涓紙灏氭湭璧嬪肩殑锛 QuerySet 锛屼絾鏄鏋滃湪鍒囩墖鏃朵娇鐢ㄦ闀垮弬鏁扮殑璇濓紝Django浼氭墽琛屾暟鎹簱鏌ヨ鐨勩

Converting to a list : You can force evaluation of a QuerySet by calling list() on it, for example:

杞寲鎴愬垪琛 锛氬 QuerySet 璋冪敤 list() 鏂规硶鐨勮瘽锛屽氨鍙互瀵瑰畠寮哄埗璧嬪硷紝姣斿锛

>>> entry_list = list(Entry.objects.all())

Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. In contrast, iterating over a QuerySet will take advantage of your database to load data and instantiate objects only as you need them.

浣嗘槸锛岄渶瑕佽鍛婄殑鏄繖鏍峰仛浼氬鑷村緢澶х殑鍐呭瓨璐熻浇锛屽洜涓篋jango浼氭妸鍒楄〃鐨勬瘡涓涓厓绱犲姞杞藉埌鍐呭瓨銆傜浉姣斾箣涓嬶紝瀵 QuerySet 杩涜杩唬浼氬埄鐢ㄦ暟鎹簱鏉ュ姞杞芥暟鎹紝骞朵笖鍦ㄩ渶瑕佺殑鏃跺欐墠浼氭妸瀵硅薄瀹炰緥鍖栥

Filtered QuerySets Are Unique

杩囨护杩囩殑鏌ヨ闆嗘槸鐙竴鏃犱簩鐨

Each time you refine a QuerySet , you get a brand-new QuerySet that is in no way bound to the previous QuerySet . Each refinement creates a separate and distinct QuerySet that can be stored, used, and reused:

浣犳瘡娆$粏鍖栦竴涓 QuerySet 閮戒細寰楀埌涓涓喘鏂扮殑 QuerySet 锛岀粷涓嶄細涓庝箣鍓嶇殑 QuerySet 鏈変换浣曠殑鐡滆憶銆傛瘡娆$殑缁嗗寲閮戒細鍒涘缓涓涓悇鑷殑鎴劧涓嶅悓鐨 QuerySet 锛屽彲浠ョ敤鏉ュ瓨鍌ㄣ佷娇鐢ㄥ拰閲嶇敤銆

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

These three QuerySets are separate. The first is a base QuerySet containing all entries that contain a headline starting with What. The second is a subset of the first, with an additional criterion that excludes records whose pub_date is greater than now. The third is a subset of the first, with an additional criterion that selects only the records whose pub_date is greater than now. The initial QuerySet (q1 ) is unaffected by the refinement process.

杩欎笁涓 QuerySet 鏄棤鍏崇殑銆傜涓涓熀纭鏌ヨ闆嗗寘鍚簡鎵鏈夋爣棰樹互What寮濮嬬殑鏉$洰銆傜浜屼釜鏌ヨ闆嗘槸绗竴涓殑瀛愰泦锛屽彧鏄繃婊ゆ帀浜 pub_date 姣斿綋鍓嶆椂闂村ぇ鐨勮褰曘傜涓変釜鏌ヨ闆嗕篃鏄涓涓殑瀛愰泦锛屽彧淇濈暀 pub_date 姣斿綋鍓嶆椂闂村ぇ鐨勮褰曘傚垵濮嬬殑 QuerySetq1 锛夋槸涓嶅彈缁嗗寲杩囩▼鐨勫奖鍝嶃

Limiting QuerySets

闄愰噺鏌ヨ闆

Use Pythons array-slicing syntax to limit your QuerySet to a certain number of results. This is the equivalent of SQLs LIMIT and OFFSET clauses.

鍙互鐢≒ython鐨勬暟鎹垏鐗囩殑璇硶鏉ラ檺瀹 QuerySet 鐨勭粨鏋滄暟閲忥紝杩欏拰SQL涓殑 LIMITOFFSET 璇彞鏄竴鏍风殑銆

For example, this returns the first five entries (LIMIT 5 ):

姣斿锛岃繖鍙ヨ繑鍥炲墠浜斾釜鏉$洰锛 LIMIT 5 锛夛細

>>> Entry.objects.all()[:5]

This returns the sixth through tenth entries (OFFSET 5 LIMIT 5 ):

杩欏彞杩斿洖绗叚鍒扮鍗佷釜鏉$洰锛 OFFSET 5 LIMIT 5 锛夛細

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

Generally, slicing a QuerySet returns a new QuerySet it doesnt evaluate the query. An exception is if you use the step parameter of Python slice syntax. For example, this would actually execute the query in order to return a list of every second object of the first ten:

涓鑸湴锛屽 QuerySet 杩涜鍒囩墖浼氳繑鍥炰竴涓柊鐨 QuerySet 锛屼絾骞朵笉鎵ц鏌ヨ銆傚鏋滀綘鍦≒ython鍒囩墖璇硶涓娇鐢ㄦ闀垮弬鏁扮殑璇濓紝灏变細鍑虹幇鐗逛緥銆備緥濡傦紝瑕佽繑鍥炲墠鍗佷釜瀵硅薄涓殑鍋跺簭鏁板璞$殑鍒楄〃鏃讹紝瀹為檯涓婁細鎵ц鏌ヨ锛

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

To retrieve a single object rather than a list (e.g., SELECT foo FROM bar LIMIT 1 ), use a simple index instead of a slice. For example, this returns the first Entry in the database, after ordering entries alphabetically by headline:

瑕佸緱鍒 鍗曚釜 瀵硅薄鑰屼笉鏄竴涓垪琛ㄦ椂锛堜緥濡 SELECT foo FROM bar LIMIT 1 锛夛紝鍙互涓嶇敤鍒囩墖鑰屾槸浣跨敤涓嬫爣銆備緥濡傦紝杩欐牱灏变細杩斿洖鏁版嵁搴撲腑瀵规爣棰樿繘琛屽瓧姣嶆帓搴忓悗鐨勭涓涓 Entry

>>> Entry.objects.order_by('headline')[0]

This is roughly equivalent to the following:

鍒氭墠杩欏彞鍜屼笅闈㈢殑澶ц嚧鐩稿綋锛

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

Note, however, that the first of these will raise IndexError while the second will raise DoesNotExist if no objects match the given criteria.

浣嗘槸瑕佽浣忥紝濡傛灉娌℃湁绗﹀悎鏉′欢鐨勮褰曠殑璇濓紝绗竴绉嶇敤娉曚細瀵艰嚧 IndexError 锛岃岀浜岀鐢ㄦ硶浼氬鑷 DoesNotExist

Query Methods That Return New QuerySets

杩斿洖鏂扮殑 QuerySets 鐨 鏌ヨ鏂规硶

Django provides a range of QuerySet refinement methods that modify either the types of results returned by the QuerySet or the way its SQL query is executed. These methods are described in the sections that follow. Some of the methods take field lookup arguments, which are discussed in detail a bit later on.

Django鎻愪緵浜嗕竴绯诲垪鐨 QuerySet 缁嗗寲鏂规硶锛屾棦鍙互淇敼 QuerySet 杩斿洖鐨勭粨鏋滅殑绫诲瀷锛屽張鍙互淇敼瀵瑰簲鐨凷QL鏌ヨ鐨勬墽琛屾柟娉曘傝繖灏辨槸杩欎竴鑺傛垜浠璁ㄨ鐨勫唴瀹广傚叾涓湁涓浜涚粏鍖栨柟娉曚細鎺ユ敹瀛楁鏌ヨ鍙傛暟锛屾垜浠◢鍚庝細璇︾粏璁ㄨ銆

filter(**lookup)
filter(**lookup)

Returns a new QuerySet containing objects that match the given lookup parameters.

杩斿洖涓涓柊鐨 QuerySet 锛屽寘鍚尮閰嶅弬鏁發ookup鐨勫璞°

exclude(**kwargs)
exclude(**kwargs)

Returns a new QuerySet containing objects that do not match the given lookup parameters.

杩斿洖涓涓柊鐨 QuerySet 锛屽寘鍚笉鍖归厤鍙傛暟kwargs鐨勫璞°

order_by(*fields)
order_by(*fields)

By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the models metadata (see Appendix B). You can override this for a particular query using the order_by() method:

榛樿鎯呭喌涓嬶紝浼氳繑鍥炰竴涓寜鐓odels鐨刴etadata涓殑``ordering``閫夐」鎺掑簭鐨刞`QuerySet``锛堣鏌ョ湅闄勫綍B锛夈備綘鍙互璋冪敤``order_by()``鏂规硶鎸夌収涓涓壒瀹氱殑瑙勫垯杩涜鎺掑簭浠ヨ鐩栭粯璁ょ殑琛屼负锛

>> Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

This result will be ordered by pub_date descending, then by headline ascending. The negative sign in front of "-pub_date" indicates descending order. Ascending order is assumed if the - is absent. To order randomly, use "?" , like so:

缁撴灉灏嗗厛瀵 pub_date 杩涜闄嶅簭鎺掑簭锛岀劧鍚庡 headline 杩涜鍗囧簭鎺掑簭銆 "-pub_date" 鍓嶉潰鐨勭鍙蜂唬琛ㄩ檷搴忔帓搴忋傚鏋滄病鏈 "-" 锛岄粯璁や负鍗囧簭鎺掑簭銆傝浣跨敤闅忔満鐨勯『搴忥紝浣跨敤 "?" 锛屾瘮濡傦細

>>> Entry.objects.order_by('?')
distinct()

Returns a new QuerySet that uses SELECT DISTINCT in its SQL query. This eliminates duplicate rows from the query results.

灏卞儚浣跨敤”SELECT DISTINCT”鍦⊿QL鏌ヨ涓鏍凤紝杩斿洖涓涓柊鐨勨漄uerySet 鈥溿傝繖娑堥櫎浜嗘煡璇㈢粨鏋滀腑鐨勯噸澶嶈銆

By default, a QuerySet will not eliminate duplicate rows. In practice, this is rarely a problem, because simple queries such as Blog.objects.all() dont introduce the possibility of duplicate result rows.

榛樿鐨勬儏鍐典笅锛 “QuerySet”骞朵笉鑳芥秷闄ら噸澶嶇殑琛屻傚湪缁冧範涓紝鍙兘浼氫骇鐢熼棶棰橈紝鍥犱负鍍 “Blog.objects”杩欎箞绠鍗曠殑鏌ヨ骞朵笉涓瀹氳兘浜х敓閲嶅鐨勮銆

However, if your query spans multiple tables, its possible to get duplicate results when a QuerySet is evaluated. Thats when youd use distinct() .

鐒惰岋紝濡傛灉浣犵殑鏌ヨ鏄琛ㄥ叧鑱旀煡璇紝閭d箞``QuerySet``鏌ヨ鐨勭粨鏋滃彲鑳戒細鏈夐噸澶嶆暟鎹.鍥犳鎴戜滑瑕佺敤``distinct()`` .

values(*fields)

Returns a special QuerySet that evaluates to a list of dictionaries instead of model-instance objects. Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects:

杩斿洖涓涓壒娈婄殑QuerySet鐩稿綋浜庝竴涓瓧鍏稿垪琛紝鑰屼笉鏄痬odel鐨勫疄渚嬨傛瘡涓瓧鍏镐唬琛ㄤ竴涓璞★紝瀹冪殑keys瀵瑰簲浜庤繖涓猰odel鐨勫睘鎬у悕銆

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
[Beatles Blog]

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

values() takes optional positional arguments, *fields , which specify field names to which the SELECT should be limited. If you specify the fields, each dictionary will contain only the field keys/values for the fields you specify. If you dont specify the fields, each dictionary will contain a key and value for every field in the database table:

values() 鏂规硶鎺ュ彈鍙夌殑浣嶇疆鍙傛暟锛, *fields 鍙傛暟瀹氫箟浜哠ELECT涓墍闄愬畾杩斿洖鐨勭壒瀹氬瓧娈电殑鍚嶇О銆傚鏋滀綘鎸囧畾浜嗚繖涓鍙傛暟锛岃繑鍥炵殑瀛楀吀涓彧浼氬寘鍚綘鍒跺畾鐨勫瓧娈电殑瀛楁鍚嶅拰瀛楁鍊笺傚鏋滀笉鎸囧畾杩欎釜鍙傛暟鐨勮瘽锛岃繑鍥炵殑瀛楀吀涓細鍖呭惈鏁版嵁琛ㄤ腑姣忎釜瀛楁鐨勫瓧娈靛悕鍜屽瓧娈靛硷細

>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]

This method is useful when you know youre only going to need values from a small number of the available fields and you wont need the functionality of a model instance object. Its more efficient to select only the fields you need to use.

褰撲綘浠庝竴灏忔暟鐩殑鍙敤瀛楁鑾峰彇鍊煎拰涓嶉渶瑕佷竴涓ā鍨嬪疄渚嬪璞$殑鏃跺欙紝杩欎釜鏂规硶寰堟湁鐢ㄣ傚畠鐨勬洿鏈夋晥鐜囩殑棰嗗煙鍙夋嫨浣犻渶瑕佷娇鐢

dates(field, kind, order)

Returns a special QuerySet that evaluates to a list of datetime.datetime objects representing all available dates of a particular kind within the contents of the QuerySet .

The field argument must be the name of a DateField or DateTimeField of your model. The kind argument must be either "year" , "month" , or "day" . Each datetime.datetime object in the result list is truncated to the given type :

  • "year" returns a list of all distinct year values for the field.

  • "month" returns a list of all distinct year/month values for the field.

  • "day" returns a list of all distinct year/month/day values for the field.

order , which defaults to 'ASC' , should be either 'ASC' or 'DESC' . This specifies how to order the results.

Here are a few examples:

>>> Entry.objects.dates('pub_date', 'year')
[datetime.datetime(2005, 1, 1)]

>>> Entry.objects.dates('pub_date', 'month')
[datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]

>>> Entry.objects.dates('pub_date', 'day')
[datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]

>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]

>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.datetime(2005, 3, 20)]
extra()

Sometimes, the Django query syntax by itself cant easily express a complex WHERE clause. For these edge cases, Django provides the extra() QuerySet modifier a hook for injecting specific clauses into the SQL generated by a QuerySet .

By definition, these extra lookups may not be portable to different database engines (because youre explicitly writing SQL code) and violate the DRY principle, so you should avoid them if possible.

Specify one or more of params , select , where , or tables . None of the arguments is required, but you should use at least one of them.

The select argument lets you put extra fields in the SELECT clause. It should be a dictionary mapping attribute names to SQL clauses to use to calculate that attribute:

>>> Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})

As a result, each Entry object will have an extra attribute, is_recent , a Boolean representing whether the entrys pub_date is greater than January 1, 2006.

The next example is more advanced; it does a subquery to give each resulting Blog object an entry_count attribute, an integer count of associated Entry objects:

>>> subq = 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
>>> Blog.objects.extra(select={'entry_count': subq})

(In this particular case, were exploiting the fact that the query will already contain the blog_blog table in its FROM clause.)

You can define explicit SQL WHERE clauses perhaps to perform nonexplicit joins by using where . You can manually add tables to the SQL FROM clause by using tables .

where and tables both take a list of strings. All where parameters are ANDed to any other search criteria:

>>> Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])

The select and where parameters described previously may use standard Python database string placeholders: '%s' to indicate parameters the database engine should automatically quote. The params argument is a list of any extra parameters to be substituted:

>>> Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

Always use params instead of embedding values directly into select or where because params will ensure values are quoted correctly according to your particular database.

濮嬬粓鐢 “params” 鑰屼笉鏄湪”select” 鎴”where”涓祵鍊硷紝鍥犱负”param”灏嗘寜鐓х壒瀹氭暟鎹簱淇濊瘉values琚纭殑寮曠敤

Heres an example of the wrong way:

涓嬮潰鏄竴涓敊璇殑鐢ㄦ硶

Entry.objects.extra(where=["headline='%s'" % name])

Heres an example of the correct way:

涓嬮潰鏄竴涓纭殑鐢ㄦ硶

Entry.objects.extra(where=['headline=%s'], params=[name])

QuerySet Methods That Do Not Return QuerySets

The following QuerySet methods evaluate the QuerySet and return something otherthan a QuerySet a single object, value, and so forth.

get(**lookup)

Returns the object matching the given lookup parameters, which should be in the format described in the Field Lookups section. This raises AssertionError if more than one object was found.

杩斿洖缁欏畾瀵硅薄鍖归厤鐨勬煡璇㈠弬鏁帮紝搴斿湪鏍煎紡璇存槑鍦ㄥ鍦版煡鎵鹃儴鍒嗭紝濡傛灉瓒呰繃涓涓璞★紝鈥淎ssertionError鈥濆紓甯稿皢琚姏鍑

get() raises a DoesNotExist exception if an object wasnt found for the given parameters. The DoesNotExist exception is an attribute of the model class, for example:

>>> Entry.objects.get(id='foo') # raises Entry.DoesNotExist

The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist , so you can target multiple DoesNotExist exceptions:

>>> from django.core.exceptions import ObjectDoesNotExist
>>> try:
...     e = Entry.objects.get(id=3)
...     b = Blog.objects.get(id=1)
... except ObjectDoesNotExist:
...     print "Either the entry or blog doesn't exist."
create(**kwargs)

This is a convenience method for creating an object and saving it all in one step. It lets you compress two common steps:

杩欎釜蹇嵎鐨勬柟娉曞彲浠ヤ竴娆℃у畬鎴愬垱寤哄苟淇濊瘉瀵硅薄銆傚畠璁╀綘瀹屾垚浜嗕笅闈袱涓楠わ細

>>> p = Person(first_name="Bruce", last_name="Springsteen")
>>> p.save()

into a single line:

>>> p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
get_or_create(**kwargs)

This is a convenience method for looking up an object and creating one if it doesnt exist. It returns a tuple of (object, created) , where object is the retrieved or created object and created is a Boolean specifying whether a new object was created.

This method is meant as a shortcut to boilerplate code and is mostly useful for data-import scripts, for example:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

This pattern gets quite unwieldy as the number of fields in a model increases. The previous example can be rewritten using get_or_create() like so:

obj, created = Person.objects.get_or_create(
    first_name = 'John',
    last_name  = 'Lennon',
    defaults   = {'birthday': date(1940, 10, 9)}
)

Any keyword arguments passed to get_or_create() except an optional one called defaults will be used in a get() call. If an object is found, get_or_create() returns a tuple of that object and False . If an object is not found, get_or_create() will instantiate and save a new object, returning a tuple of the new object and True . The new object will be created according to this algorithm:

adsf

defaults = kwargs.pop('defaults', {})
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
params.update(defaults)
obj = self.model(**params)
obj.save()

In English, that means start with any non-'defaults' keyword argument that doesnt contain a double underscore (which would indicate a nonexact lookup). Then add the contents of defaults , overriding any keys if necessary, and use the result as the keyword arguments to the model class.

If you have a field named defaults and want to use it as an exact lookup in get_or_create() , just use 'defaults__exact' like so:

Foo.objects.get_or_create(
    defaults__exact = 'bar',
    defaults={'defaults': 'baz'}
)

Note

As mentioned earlier, get_or_create() is mostly useful in scripts that need to parse data and create new records if existing ones arent available. But if you need to use get_or_create() in a view, please make sure to use it only in POST requests unless you have a good reason not to. GET requests shouldnt have any effect on data; use POST whenever a request to a page has a side effect on your data.

count()

Returns an integer representing the number of objects in the database matching the QuerySet . count() never raises exceptions. Heres an example:

# Returns the total number of entries in the database.
>>> Entry.objects.count()
4

# Returns the number of entries whose headline contains 'Lennon'
>>> Entry.objects.filter(headline__contains='Lennon').count()
1

count() performs a SELECT COUNT(*) behind the scenes, so you should always use count() rather than loading all of the records into Python objects and calling len() on the result.

Depending on which database youre using (e.g., PostgreSQL or MySQL), count() may return a long integer instead of a normal Python integer. This is an underlying implementation quirk that shouldnt pose any real-world problems.

in_bulk(id_list)

Takes a list of primary key values and returns a dictionary mapping each primary key value to an instance of the object with the given ID, for example:

>>> Blog.objects.in_bulk([1])
{1: Beatles Blog}
>>> Blog.objects.in_bulk([1, 2])
{1: Beatles Blog, 2: Cheddar Talk}
>>> Blog.objects.in_bulk([])
{}

IDs of objects that dont exist are silently dropped from the result dictionary. If you pass in_bulk() an empty list, youll get an empty dictionary.

latest(field_name=None)

Returns the latest object in the table, by date, using the field_name provided as the date field. This example returns the latest Entry in the table, according to the pub_date field:

>>> Entry.objects.latest('pub_date')

If your models Meta specifies get_latest_by , you can leave off the field_name argument to latest() . Django will use the field specified in get_latest_by by default.

Like get() , latest() raises DoesNotExist if an object doesnt exist with the given parameters.

Field Lookups

Field lookups are how you specify the meat of an SQL WHERE clause. Theyre specified as keyword arguments to the QuerySet methods filter() , exclude() , and get() .

Basic lookup keyword arguments take the form field__lookuptype=value (note the double underscore). For example:

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

translates (roughly) into the following SQL:

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

If you pass an invalid keyword argument, a lookup function will raise TypeError .

The supported lookup types follow.

exact

Performs an exact match:

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

This matches any object with the exact headline Man bites dog.

If you dont provide a lookup type that is, if your keyword argument doesnt contain a double underscore the lookup type is assumed to be exact .

For example, the following two statements are equivalent:

渚嬪锛屼笅闈袱涓鍙ユ槸绛夋晥鐨勶細

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied

This is for convenience, because exact lookups are the common case.

iexact

Performs a case-insensitive exact match:

瀛楃涓叉瘮杈冿紙澶у皬鍐欐棤鍏筹級

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

This will match 'Beatles Blog' , 'beatles blog' , 'BeAtLes BLoG' , and so forth.

contains

Performs a case-sensitive containment test:

鎵ц涓ユ牸鍖哄垎澶у皬鍐欑殑鍐呭鍖呭惈妫娴嬶細

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

This will match the headline 'Today Lennon honored' but not 'today lennon honored' .

杩欏皢浼氬尮閰嶆爣棰樹负``’Today Lennon honored’`` 鐨勶紝鑰屼笉鍖归厤 ``‘today lennon honored’``

System Message: WARNING/2 (<string>, line 2781); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (<string>, line 2781); backlink

Inline literal start-string without end-string.

SQLite doesnt support case-sensitive LIKE statements; when using SQLite,``contains`` acts like icontains .

SQLite涓嶆敮鎸佷弗鏍煎尯鍒嗗ぇ灏忓啓鐨 LIKE 璇彞锛屾墍浠ュ湪浣跨敤SQLite鏃禶`contains``鐨勪綔鐢ㄥ拰``icontains``涓鏍枫

Escaping Percent Signs and Underscores in LIKE Statements

闄や簡LIKE璇彞涓殑鐧惧垎鍙峰拰涓嬪垝绾

The field lookups that equate to LIKE SQL statements (iexact , contains , icontains , startswith , istartswith , endswith , and iendswith ) will automatically escape the two special characters used in LIKE statements the percent sign and the underscore. (In a LIKE statement, the percent sign signifies a multiple-character wildcard and the underscore signifies a single-character wildcard.)

浣跨敤鐩稿綋浜巂`LIKE``鐨凷QL鏌ユ壘璇彞(iexact , contains , icontains, startswith, istartswith, endswith, 鍜宍`iendswith``)鏃讹紝浼氳嚜鍔ㄧ殑鎺掗櫎``LIKE``璇彞涓娇鐢ㄧ殑涓や釜鐗规畩绗﹀彿锛氱櫨鍒嗗彿銆佷笅鍒掔嚎銆傦紙鍦ㄤ竴鏉`LIKE``璇彞涓紝鐧惧垎鍙锋槸澶氫釜瀛楃鐨勯氶厤绗︼紝涓嬪垝绾挎槸鍗曚釜瀛楃鐨勯氶厤绗︼級

This means things should work intuitively, so the abstraction doesnt leak. For example, to retrieve all the entries that contain a percent sign, just use the percent sign as any other character:

杩欐剰鍛崇潃浣跨敤鐨勭洿瑙傛э紝鎵浠ヤ笉浼氫骇鐢熸紡鎻愬彇鐨勩備緥濡傦紝鏌ユ壘鎵鏈夊惈鏈変竴涓櫨鍒嗗彿鐨勯」锛屽彧闇瑕佹兂鐢ㄥ叾浠栧瓧绗︿竴鏍风敤涓涓櫨鍒嗗彿锛

Entry.objects.filter(headline__contains='%')

Django takes care of the quoting for you. The resulting SQL will look something like this:

Django 涓轰綘澶勭悊浜嗚繖涓寮曠敤銆備骇鐢熺殑SQL濡備笅锛

SELECT ... WHERE headline LIKE '%\%%';

The same goes for underscores. Both percentage signs and underscores are handled for you transparently.

icontains

Performs a case-insensitive containment test:

鎵ц涓涓拷鐣ュぇ灏忓啓鐨勫唴瀹瑰寘鍚娴嬶細

>>> Entry.objects.get(headline__icontains='Lennon')

Unlike contains , icontains will match 'today lennon honored' .

涓巂`contains``涓嶅悓, icontains 鍖归厤 'today lennon honored'

gt, gte, lt, and lte

These represent greater than, greater than or equal to, less than, and less than or equal to:

杩欎簺鍗冲ぇ浜庯紝澶т簬鎴栫瓑浜庯紝灏忎簬锛屽皬浜庢垨绛変簬:

>>> Entry.objects.filter(id__gt=4)
>>> Entry.objects.filter(id__lt=15)
>>> Entry.objects.filter(id__gte=0)

These queries return any object with an ID greater than 4, an ID less than 15, and an ID greater than or equal to 1, respectively.

杩欎簺鏌ヨ鍒嗗埆杩斿洖 ID 澶т簬 4锛孖D 灏忎簬 15锛屼互鍙 ID 澶т簬绛変簬 0 鐨勫璞°

Youll usually use these on numeric fields. Be careful with character fields since character order isnt always what youd expect (i.e., the string 4 sorts after the string 10).

in

Filters where a value is on a given list:

绛涢夊嚭鍖呭惈鍦ㄧ粰瀹氬垪琛ㄤ腑鐨勬暟鎹細

Entry.objects.filter(id__in=[1, 3, 4])

This returns all objects with the ID 1, 3, or 4.

杩欎細杩斿洖鎵鏈塈D涓1锛3锛屾垨4鐨勬潯鐩

startswith

Performs a case-sensitive starts-with:

鍖哄垎澶у皬鍐欑殑寮澶村尮閰嶏細

>>> Entry.objects.filter(headline__startswith='Will')

This will return the headlines Will he run? and Willbur named judge, but not Who is Will? or will found in crypt.

杩欏皢杩斿洖鏍囬Will he run?鍜學illbur named judge锛屼絾鏄笉浼氳繑鍥濿ho is Will? 鍜寃ill found in crypt.

istartswith

Performs a case-insensitive starts-with:

>>> Entry.objects.filter(headline__istartswith='will')

This will return the headlines Will he run?, Willbur named judge, and will found in crypt, but not Who is Will?

endswith and iendswith

Perform case-sensitive and case-insensitive ends-with:

鍖哄垎澶у皬鍐欏拰蹇界暐澶у皬鍐欑殑鏈熬鍖归厤銆

>>> Entry.objects.filter(headline__endswith='cats')
>>> Entry.objects.filter(headline__iendswith='cats')

range

Performs an inclusive range check:

>>> start_date = datetime.date(2005, 1, 1)
>>> end_date = datetime.date(2005, 3, 31)
>>> Entry.objects.filter(pub_date__range=(start_date, end_date))

You can use range anywhere you can use BETWEEN in SQL for dates, numbers, and even characters.

year, month, and day

For date/datetime fields, perform exact year, month, or day matches:

瀵筪ate/datetime绫诲瀷涓ユ牸鍖归厤骞淬佹湀鎴栨棩锛

# Year lookup
>>>Entry.objects.filter(pub_date__year=2005)

# Month lookup -- takes integers
>>> Entry.objects.filter(pub_date__month=12)

# Day lookup
>>> Entry.objects.filter(pub_date__day=3)

# Combination: return all entries on Christmas of any year
>>> Entry.objects.filter(pub_date__month=12, pub_date_day=25)

isnull

Takes either True or False , which correspond to SQL queries of IS NULL and IS NOT NULL , respectively:

浣跨敤``True``鎴朻`False``锛屽垯鍒嗗埆鐩稿綋浜嶴QL璇彞涓殑``IS NULL``鍜宍`IS NOT NULL``:

>>> Entry.objects.filter(pub_date__isnull=True)

__isnull=True vs. __exact=None

There is an important difference between __isnull=True and __exact=None . __exact=None will always return an empty result set, because SQL requires that no value is equal to NULL . __isnull determines if the field is currently holding the value of NULL without performing a comparison.

__isnull=True``鍜宍`__exact=None``鏈変竴涓緢涓昏鐨勫尯鍒傚洜涓篠QL瑙勫畾鏃犲煎氨绛変簬``NULL 锛屾墍浠`__exact=None``浼 鎬绘槸 杩斿洖涓涓┖鐨勭粨鏋溿俙`__isnull``鍒欏彇鍐充簬璇ラ槇鏄惁褰撳墠鏈夊 ``NULL``鑰屼笉杩涜姣旇緝銆

System Message: WARNING/2 (<string>, line 3288); backlink

Inline literal start-string without end-string.

The pk Lookup Shortcut

For convenience, Django provides a pk lookup type, which stands for primary_key.

In the example Blog model, the primary key is the id field, so these three statements are equivalent:

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact

The use of pk isnt limited to __exact queries any query term can be combined with pk to perform a query on the primary key of a model:

# Get blogs entries  with id 1, 4, and 7
>>> Blog.objects.filter(pk__in=[1,4,7])

# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)

pk lookups also work across joins. For example, these three statements are equivalent:

>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3) # __exact is implied
>>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact

Complex Lookups with Q Objects

浣跨敤Q瀵硅薄鍋氳仈鍚堟煡鎵

Keyword argument queries in filter() and so on are ANDed together. If you need to execute more complex queries (e.g., queries with OR statements), you can use Q objects.

``filter()``绛夎鍙ョ殑鍙傛暟閮芥槸鍙朅ND杩愮畻銆傚鏋滄兂瑕佹墽琛屾洿澶氱殑鑱斿悎璇彞锛堝``OR``璇彞锛夛紝浣犲彲浠ヤ娇鐢 ``Q``瀵硅薄銆

System Message: WARNING/2 (<string>, line 3434); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (<string>, line 3434); backlink

Inline literal start-string without end-string.

A Q object (django.db.models.Q ) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in the Field Lookups section.

Q 瀵硅薄 (django.db.models.Q ) 鏄竴涓敤鏉ュ泭鎷弬鏁伴棿杩炴帴鐨勫璞°傝繖浜涘弬鏁颁細鏀惧湪鎸囧畾鐨勫煙鏌ヨ鐨勪綅缃

For example, this Q object encapsulates a single LIKE query:

渚嬪锛岃繖涓猔`Q``瀵硅薄灏卞寘鎷簡涓涓猔`LIKE``鏉′欢锛

Q(question__startswith='What')

Q objects can be combined using the & and | operators. When an operator is used on two Q objects, it yields a new Q object. For example, this statement yields a single Q object that represents the OR of two "question__startswith" queries:

Q 瀵硅薄鍙互鐢ㄨ繍绠楃 &| 鏉ヨ仈鍚堛傚綋涓涓繍绠楃杩炴帴涓や釜 Q 瀵硅薄鏃讹紝灏变骇鐢熶簡涓涓柊鐨 Q 瀵硅薄銆備緥濡傦紝杩欏彞鐢熸垚涓涓崟涓鐨 Q 瀵硅薄銆傜浉褰撲簬涓や釜``”question__startswith”``鏉′欢鐨凮R锛

System Message: WARNING/2 (<string>, line 3482); backlink

Inline literal start-string without end-string.

Q(question__startswith='Who') | Q(question__startswith='What')

This is equivalent to the following SQL WHERE clause:

杩欑浉褰撲簬濡備笅鐨凷QL ``WHERE``璇彞锛

System Message: WARNING/2 (<string>, line 3509); backlink

Inline literal start-string without end-string.

WHERE question LIKE 'Who%' OR question LIKE 'What%'

You can compose statements of arbitrary complexity by combining Q objects with the & and | operators. You can also use parenthetical grouping.

浣犲彲浠ョ敤杩愮畻绗`&``鍜 |``杩炴帴``Q 瀵硅薄缁勬垚浠绘剰澶嶆潅鐨勮鍙ャ備綘涔熷彲浠ヤ娇鐢ㄩ檮鍔犵粍銆

Each lookup function that takes keyword arguments (e.g., filter() , exclude() , get() ) can also be passed one or more Q objects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be ANDed together, for example:

浠讳竴甯﹀叧閿瓧鍙傛暟鐨勭殑鏌ユ壘鍑芥暟锛堝``filter()`` , exclude() ,``get()`` 锛変篃鍙皢涓鍒板涓猔`Q`` 瀵硅薄浣滀负鍙傛暟銆傚鏋滃湪涓涓煡璇㈠嚱鏁颁腑浣跨敤澶氫釜``Q`` 瀵硅薄鍙傛暟锛岃繖浜涘弬鏁颁細琚叏浣撳仛AND杩愮畻锛屼緥濡傦細

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

roughly translates into the following SQL:

澶ц嚧涓婂彲杞崲涓哄涓嬬殑SQL锛

SELECT * from polls WHERE question LIKE 'Who%'
    AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

Lookup functions can mix the use of Q objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q objects) are ANDed together. However, if a Q object is provided, it must precede the definition of any keyword arguments. For example, the following:

鏌ヨ鍑芥暟鍙互娣峰悎浣跨敤``Q``瀵硅薄鍜屽叧閿瓧浣滃弬鏁般傛墍鏈夌殑鍙傛暟浣滀负鏌ヨ鍑芥暟鐨勬潯浠讹紙鏃犺浠栦滑鏄叧閿瓧鍙傛暟杩樻槸``Q``瀵硅薄锛夎繘琛孉ND杩愮畻銆傜劧鑰岋紝濡傛灉灏嗕竴涓猔`Q``瀵硅薄浣滀负鏉′欢锛屽垯瀹冨繀椤绘斁鍦ㄦ墍鏈夊叧閿瓧鍙傛暟瀹氫箟涔嬪墠銆傚氨鍍忎笅闈㈣繖鏍凤細

Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith='Who')

would be a valid query, equivalent to the previous example, but this:

杩欐槸姝g‘鐨勶紝灏辩浉褰撲簬涔嬪墠鐨勪緥瀛愩備絾濡傛灉杩欐牱锛

# INVALID QUERY
Poll.objects.get(
    question__startswith='Who',
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

would not be valid.

灏辨槸涓嶆纭殑銆

You can find some examples online at http://www.djangoproject.com/documentation/0.96/models/or_lookups/.

鍦ㄤ簰鑱旂綉涓婁綘鍙互鎵惧埌涓浜涗緥瀛 http://www.djangoproject.com/documentation/0.96/models/or_lookups/.

鍏崇郴瀵硅薄

When you define a relationship in a model (i.e., a ForeignKey , OneToOneField , or ManyToManyField ), instances of that model will have a convenient API to access the related object(s).

褰撲綘瀹氫箟浜嗕竴涓叧绯绘ā鍨嬶紙渚嬪锛氬閿紝涓瀵逛竴鍩燂紝鎴栧瀵瑰鍩燂級锛岃繖涓妯″紡鐨勫疄渚嬪皢鏈変竴涓柟渚跨殑API鏉ヨ闂浉鍏崇殑瀵硅薄銆

For example, an Entry object e can get its associated Blog object by accessing the blog attribute e.blog .

渚嬪锛孍ntry瀵硅薄e鑳借幏寰楃浉鍏崇殑blog瀵硅薄璁块棶鍗氬灞炴.blog

Django also creates API accessors for the other side of the relationship the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all() .

All examples in this section use the sample Blog , Author , and Entry models defined at the top of this page.

鏈妭灏嗙户缁娇鐢ㄤ箣鍓嶅畾涔夌殑”Blog”, “Author”, “Entry”妯″瀷浣滀负渚嬪瓙

Lookups That Span Relationships

璺ㄨ秺鍏崇郴鏌ユ壘

Django offers a powerful and intuitive way to follow relationships in lookups, taking care of the SQL JOIN s for you automatically behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.

This example retrieves all Entry objects with a Blog whose name is 'Beatles Blog' :

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

This spanning can be as deep as youd like.

杩欒法瓒婂彲涔嬫繁鍙兂鑰岀煡锛

It works backward, too. To refer to a reverse relationship, just use the lowercase name of the model.

This example retrieves all Blog objects that have at least one Entry whose headline contains 'Lennon' :

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

Foreign Key Relationships

澶栭敭鍏崇郴

If a model has a ForeignKey , instances of that model will have access to the related (foreign) object via a simple attribute of the model, for example:

濡傛灉涓涓ā鍨嬮噷闈㈡湁涓涓 ForeignKey 瀛楁锛岄偅涔堝畠鐨勫疄渚嬪寲瀵硅薄鍙互寰堣交鏄撶殑閫氳繃妯″瀷鐨勫睘鎬ф潵璁块棶涓庡叾鍏宠仈鐨勫叧绯诲璞★紝渚嬪锛

e = Entry.objects.get(id=2)
e.blog # Returns the related Blog object.

You can get and set via a foreign key attribute. As you may expect, changes to the foreign key arent saved to the database until you call save() , for example:

浣犲彲浠ラ氳繃澶栭敭灞炴ф潵鑾峰彇骞惰缃叧鑱旂殑澶栭敭瀵硅薄銆傚浣犳墍鏂欙紝鍗曠函淇敼澶栭敭鐨勬搷浣滄槸涓嶈兘椹笂灏嗕慨鏀圭殑鍐呭鍚屾鍒版暟鎹簱涓殑锛屼綘杩樺繀椤昏皟鐢 save() 鏂规硶鎵嶈锛屼緥濡傦細

e = Entry.objects.get(id=2)
e.blog = some_blog
e.save()

If a ForeignKey field has null=True set (i.e., it allows NULL values), you can assign None to it:

濡傛灉涓涓 ForeignKey 瀛楁璁剧疆浜 null=True 閫夐」锛堝厑璁 NULL 鍊硷級鏃讹紝浣犲彲浠ュ皢 None 璧嬬粰瀹冿紙璇戞敞:浣嗙函璁剧疆null=True鍏跺疄杩樻槸涓嶈鐨,浼氭姏鍑哄紓甯哥殑,杩樹笉椤绘妸blank=True涔熻浜嗘墠琛,涓嶇煡閬撲粈涔堝師鍥,鎴戜竴鐩翠互鏉ラ兘鏈夌偣鎬鐤戣繖鏄釜BUG)锛

e = Entry.objects.get(id=2)
e.blog = None
e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Forward access to one-to-many relationships is cached the first time the related object is accessed. Subsequent accesses to the foreign key on the same object instance are cached, for example:

e = Entry.objects.get(id=2)
print e.blog  # Hits the database to retrieve the associated Blog.
print e.blog  # Doesn't hit the database; uses cached version.

Note that the select_related() QuerySet method recursively prepopulates the cache of all one-to-many relationships ahead of time:

e = Entry.objects.select_related().get(id=2)
print e.blog  # Doesn't hit the database; uses cached version.
print e.blog  # Doesn't hit the database; uses cached version.

select_related() is documented in the QuerySet Methods That Return New QuerySets section.

Reverse Foreign Key Relationships

澶栭敭鐨勫弽寮曠敤鍏崇郴

Foreign key relationships are automatically symmetrical a reverse relationship is inferred from the presence of a ForeignKey pointing to another model.

澶栭敭鍏崇郴鏄嚜鍔ㄥ绉板弽寮曠敤鍏崇郴鐨,杩欏彲鐢变竴涓閿彲浠ユ寚鍚戝彟涓涓ā鍨嬭屽緱鐭.

If a model has a ForeignKey , instances of the foreign key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set , where FOO is the source model name, lowercased. This Manager returns QuerySets , which can be filtered and manipulated as described in the Retrieving Objects section.

濡傛灉涓涓簮妯″瀷鍚湁涓涓閿,閭d箞瀹冪殑澶栭敭妯″瀷鐨勫疄渚,鍙互鍒╃敤”Manager”杩斿洖杩欎釜婧愭ā鍨嬬殑鎵鏈夊疄渚.榛樿鐨勮繖涓”Manager”鍙仛”FOO_set”,杩欎釜”FOO”鏄簮妯″瀷鐨勫悕瀛,灏忓啓瀛楁瘝,杩欎釜”Manager”灏嗚繑鍥”QuerySets”,瀵硅繖涓猀uerySets杩涜杩囨护鍜屾搷浣,灏卞儚鍦ㄦ绱㈠璞$珷鑺備腑浠嬬粛鐨.

Heres an example:

b = Blog.objects.get(id=1)
b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()

You can override the FOO_set name by setting the related_name parameter in the ForeignKey() definition. For example, if the Entry model was altered to blog = ForeignKey(Blog, related_name='entries') , the preceding example code would look like this:

閫氳繃鍦”ForeignKey()”涓畾涔塺elated_name鍙傛暟,浣犲彲浠ラ噸杞”FOO_set”鍚嶅瓧.涓句緥,濡傛灉鎶”Entry”妯″瀷淇敼涓”blog =ForeignKey(Blog, related_name=’entries’)”,澶勭悊渚嬪瓙鐨勪唬鐮佸涓:

b = Blog.objects.get(id=1)
b.entries.all() # Returns all Entry objects related to Blog.

# b.entries is a Manager that returns QuerySets.
b.entries.filter(headline__contains='Lennon')
b.entries.count()

You cannot access a reverse ForeignKey Manager from the class; it must be accessed from an instance:

浣犱笉鑳界洿鎺ヨ闂繖涓被鐨剅everse “ForeignKey” “Manager”;瀹冨繀椤婚氳繃涓涓疄渚:

Blog.entry_set # Raises AttributeError: "Manager must be accessed via instance".

In addition to the QuerySet methods defined in the Retrieving Objects section, the ForeignKey Manager has these additional methods:

add(obj1, obj2, ...) : Adds the specified model objects to the related object set, for example:

b = Blog.objects.get(id=1)
e = Entry.objects.get(id=234)
b.entry_set.add(e) # Associates Entry e with Blog b.

create(**kwargs) : Creates a new object, saves it, and puts it in the related object set. It returns the newly created object:

b = Blog.objects.get(id=1)
e = b.entry_set.create(headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))
# No need to call e.save() at this point -- it's already been saved.

This is equivalent to (but much simpler than) the following:

b = Blog.objects.get(id=1)
e = Entry(blog=b, headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))
e.save()

Note that theres no need to specify the keyword argument of the model that defines the relationship. In the preceding example, we dont pass the parameter blog to create() . Django figures out that the new Entry objects blog field should be set to b .

娉ㄦ剰鍒,杩欏苟娌℃湁蹇呰鍦ㄥ畾涔変簡澶栭敭鍏崇郴鐨勬ā鍨嬩腑瀹氫箟鍏抽敭瀛楀弬鏁.鍦ㄤ箣鍓嶇殑渚嬪瓙涓,鎴戜滑娌℃湁浼犻”blog”鍙傛暟缁”create()”.Django浼氳В鍐宠繖涓柊寤虹殑”Entry”瀵硅薄鐨刡log瀛楁鍊艰缃负b.

remove(obj1, obj2, ...) : Removes the specified model objects from the related object set:

b = Blog.objects.get(id=1)
e = Entry.objects.get(id=234)
b.entry_set.remove(e) # Disassociates Entry e from Blog b.

In order to prevent database inconsistency, this method only exists on ForeignKey objects where null=True . If the related field cant be set to None (NULL ), then an object cant be removed from a relation without being added to another. In the preceding example, removing e from b.entry_set() is equivalent to doing e.blog = None , and because the blog ForeignKey doesnt have null=True , this is invalid.

涓轰簡闃绘鏁版嵁搴撶殑涓嶇ǔ瀹,杩欑鏂规硶鍙兘瀵瑰惈鏈夊閿瓧娈靛苟涓旇瀛楁鍙互涓簄ull鐨勫璞℃湁鏁,濡傛灉鍏宠仈瀛楁涓嶈兘璁剧疆涓”None”(“NULL”),then an object can’t be removed from a relation without being added to another. 鍦ㄤ箣鍓嶇殑渚嬪瓙涓,浠巂`b.entry_set()`` 涓垹闄,鐩稿綋浜”e.blog=None”,鍥犱负杩欎釜”blog”“ForeignKey”涓嶈兘”nullTrue”,鎵浠ヨ繖鏄棤鏁堢殑鍒犻櫎.

clear() : Removes all objects from the related object set:

b = Blog.objects.get(id=1)
b.entry_set.clear()

Note this doesnt delete the related objects it just disassociates them.

娉ㄦ剰: 杩欏苟涓嶄細鍒犻櫎鍏宠仈鐨勫璞,浠呮槸鏂紑涓庡畠浠殑鍏宠仈

Just like remove() , clear() is only available on ForeignKey``s where ``null=True .

To assign the members of a related set in one fell swoop, just assign to it from any iterable object, for example:

閫氳繃缁欏叧鑱旈泦鍒嗛厤涓涓彲杩唬鐨勫璞″彲浠ュ疄鐜颁竴鑲¤剳鐨勬妸澶氫釜瀵硅薄璧嬬粰瀹

b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]

If the clear() method is available, any pre-existing objects will be removed from the entry_set before all objects in the iterable (in this case, a list) are added to the set. If the clear() method is not available, all objects in the iterable will be added without removing any existing elements.

Each reverse operation described in this section has an immediate effect on the database. Every addition, creation, and deletion is immediately and automatically saved to the database.

Many-to-Many Relationships

澶氬澶氬叧绯

Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a reverse one-to-many relationship (described in the previous section).

鍦ㄥ瀵瑰鍏崇郴鐨勪袱绔紝閮藉彲浠ラ氳繃鐩稿簲鐨凙PI鏉ヨ闂彟澶栫殑涓绔 API鐨勫伐浣滄柟寮忚窡鍓嶄竴鑺傛墍鎻忚堪鐨勫弽鍚戜竴瀵瑰鍏崇郴宸笉澶氥

The only difference is in the attribute naming: the model that defines the ManyToManyField uses the attribute name of that field itself, whereas the reverse model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships).

鍞竴鐨勪笉鍚屽湪浜庡睘鎬х殑鍛藉悕锛氬畾涔変簡``ManyToManyField``鐨刴odel鐨勫疄渚嬩娇鐢ㄥ睘鎬у悕绉版湰韬紝鍙﹀涓绔殑model鐨勫疄渚嬪垯浣跨敤model鍚嶇О鐨勫皬鍐欏姞涓奰`_set``鏉ユ椿寰楀叧鑱旂殑瀵硅薄闆嗭紙灏辫窡鍙嶅悜涓瀵瑰鍏崇郴涓鏍凤級

An example makes this concept easier to understand:

鐢ㄤ緥瀛愭潵璇存槑涓涓嬪ぇ瀹朵細鏇村鏄撶悊瑙o細

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

Like ForeignKey , ManyToManyField can specify related_name . In the preceding example, if the ManyToManyField in Entry had specified related_name='entries' , then each Author instance would have an entries attribute instead of entry_set .

How Are the Backward Relationships Possible?

Other object-relational mappers require you to define relationships on both sides. The Django developers believe this is a violation of the DRY (Dont Repeat Yourself) principle, so Django requires you to define the relationship on only one end. But how is this possible, given that a model class doesnt know which other model classes are related to it until those other model classes are loaded?

The answer lies in the INSTALLED_APPS setting. The first time any model is loaded, Django iterates over every model in INSTALLED_APPS and creates the backward relationships in memory as needed. Essentially, one of the functions of INSTALLED_APPS is to tell Django the entire model domain.

Deleting Objects

鍒犻櫎瀵硅薄

The delete method, conveniently, is named delete() . This method immediately deletes the object and has no return value:

e.delete()

You can also delete objects in bulk. Every QuerySet has a delete() method, which deletes all members of that QuerySet . For example, this deletes all Entry objects with a pub_date year of 2005:

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

When Django deletes an object, it emulates the behavior of the SQL constraint ON DELETE CASCADE in other words, any objects that had foreign keys pointing at the object to be deleted will be deleted along with it, for example:

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

Note that delete() is the only QuerySet method that is not exposed on a Manager itself. This is a safety mechanism to prevent you from accidentally requesting Entry.objects.delete() and deleting all the entries. If you do want to delete all the objects, then you have to explicitly request a complete query set:

Entry.objects.all().delete()

Extra Instance Methods

In addition to save() and delete() , a model object might get any or all of the following methods.

get_FOO_display()

For every field that has choices set, the object will have a get_FOO_display() method, where FOO is the name of the field. This method returns the human-readable value of the field. For example, in the following model:

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)

each Person instance will have a get_gender_display() method:

姣忎竴涓 Person 瀹炰緥閮藉皢鏈変竴涓 get_gender_display() 鏂规硶锛

>>> p = Person(name='John', gender='M')
>>> p.save()
>>> p.gender
'M'
>>> p.get_gender_display()
'Male'

get_next_by_FOO(**kwargs) and get_previous_by_FOO(**kwargs)

For every DateField and DateTimeField that does not have null=True , the object will have get_next_by_FOO() and get_previous_by_FOO() methods, where FOO is the name of the field. This returns the next and previous object with respect to the date field, raising the appropriate DoesNotExist exception when appropriate.

瀵逛簬浠讳綍涓嶅厑璁哥┖鍊肩殑DateField鍜孌ateTimeField瀛楁锛屽皢浼氭湁”get_next_by_FOO()”鍜”get_previous_by_FOO()”杩欎袱涓柟娉曘侳OO琛ㄧず瀛楁鍚嶃傝繖涓や釜鏂规硶灏嗘牴鎹粰瀹氱殑鏃ユ湡瀛楁杩斿洖鍏跺墠涓涓佸悗涓涓璞★紝閫傚綋鐨勬椂鍊欎細鎶涘嚭”DoesNotExist”鐨勫紓甯搞

Both methods accept optional keyword arguments, which should be in the format described in the Field Lookups section.

涓ょ鏂规硶閮芥帴鍙楀彲閫夌殑鍏抽敭璇嶅弬鏁帮紝杩欎簺鍙傛暟搴旇閬靛惊 鈥滃煙鏌ヨ鈥濅竴鑺備腑鐨勬牸寮忋

Note that in the case of identical date values, these methods will use the ID as a fallback check. This guarantees that no records are skipped or duplicated. For a full example, see the lookup API samples at http://www.djangoproject.com/documentation/0.96/models/lookup/.

get_FOO_filename()

For every FileField , the object will have a get_FOO_filename() method, where FOO is the name of the field. This returns the full filesystem path to the file, according to your MEDIA_ROOT setting.

Note that ImageField is technically a subclass of FileField , so every model with an ImageField will also get this method.

娉ㄦ剰鍒 ``ImageField``浠庢妧鏈笂鏄 ``FileField``鐨勫瓙绫伙紝鎵浠ユ瘡涓湁``ImageField``鐨勬ā鍨嬮兘鏈夎繖涓柟娉曘

System Message: WARNING/2 (<string>, line 4777); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (<string>, line 4777); backlink

Inline literal start-string without end-string.

get_FOO_url()

For every FileField , the object will have a get_FOO_url() method, where FOO is the name of the field. This returns the full URL to the file, according to your MEDIA_URL setting. If the value is blank, this method returns an empty string.

get_FOO_size()

For every FileField , the object will have a get_FOO_size() method, where FOO is the name of the field. This returns the size of the file, in bytes. (Behind the scenes, it uses os.path.getsize .)

save_FOO_file(filename, raw_contents)

For every FileField , the object will have a save_FOO_file() method, where FOO is the name of the field. This saves the given file to the filesystem, using the given file name. If a file with the given file name already exists, Django adds an underscore to the end of the file name (but before the extension) until the file name is available.

get_FOO_height() and get_FOO_width()

For every ImageField , the object will have get_FOO_height() and get_FOO_width() methods, where FOO is the name of the field. This returns the height (or width) of the image, as an integer, in pixels.

Shortcuts

鎹峰緞

As you develop views, you will discover a number of common idioms in the way you use the database API. Django encodes some of these idioms as shortcuts that can be used to simplify the process of writing views. These functions are in the django.shortcuts module.

get_object_or_404()

One common idiom to use get() and raise Http404 if the object doesnt exist. This idiom is captured by get_object_or_404() . This function takes a Django model as its first argument and an arbitrary number of keyword arguments, which it passes to the default managers get() function. It raises Http404 if the object doesnt exist, for example:

# Get the Entry with a primary key of 3
e = get_object_or_404(Entry, pk=3)

When you provide a model to this shortcut function, the default manager is used to execute the underlying get() query. If you dont want to use the default manager, or if you want to search a list of related objects, you can provide get_object_or_404() with a Manager object instead:

# Get the author of blog instance e with a name of 'Fred'
a = get_object_or_404(e.authors, name='Fred')

# Use a custom manager 'recent_entries' in the search for an
# entry with a primary key of 3
e = get_object_or_404(Entry.recent_entries, pk=3)

get_list_or_404()

get_list_or_404 behaves the same way as get_object_or_404() , except that it uses filter() instead of get() . It raises Http404 if the list is empty.

get_list_or_404 琛屼负涓 get_object_or_404() 鐩稿悓锛屼絾鏄畠鐢 filter() 鍙栦唬浜 get() 銆傚鏋滃垪琛ㄤ负绌猴紝瀹冨皢寮曞彂 Http404

Falling Back to Raw SQL

鍥炲綊鍘熷鐨凷QL鎿嶄綔

If you find yourself needing to write an SQL query that is too complex for Djangos database mapper to handle, you can fall back into raw SQL statement mode.

濡傛灉浣犻渶瑕佸啓涓涓猄QL鏌ヨ锛屼絾鏄敤Django鐨勬暟鎹簱鏄犲皠鏉ュ疄鐜扮殑璇濆お澶嶆潅浜嗭紝閭d箞浣犲彲浠ヨ冭檻浣跨敤鍘熷鐨凷QL璇彞銆

The preferred way to do this is by giving your model custom methods or custom manager methods that execute queries. Although theres nothing in Django that requires database queries to live in the model layer, this approach keeps all your data access logic in one place, which is smart from a code organization standpoint. For instructions, see Appendix B..

瑙e喅杩欎釜闂鐨勬瘮杈冨ソ鐨勬柟娉曟槸锛岀粰妯″潡鍐欎竴涓嚜瀹氫箟鐨勬柟娉曟垨鑰呯鐞嗗櫒鏂规硶鏉ユ墽琛屾煡璇€傚敖绠″湪Django涓紝鏁版嵁搴撴煡璇㈠湪妯″潡涓病鏈変换浣曞瓨鍦ㄧ殑 蹇呰鎬 锛屼絾鏄繖绉嶈В鍐虫柟妗堜娇浣犵殑鏁版嵁璁块棶鍦ㄩ昏緫涓婁繚鎸佷竴鑷达紝鑰屼笖浠庣粍缁囦唬鐮佺殑瑙掑害璁蹭篃鏇寸伒娲汇傛搷浣滄寚鍗楄闄勫綍B銆

Finally, its important to note that the Django database layer is merely an interface to your database. You can access your database via other tools, programming languages, or database frameworks theres nothing Django-specific about your database.

鏈鍚庯紝璇疯浣廌jango鐨勬暟鎹簱灞備粎浠呮槸璁块棶鏁版嵁搴撶殑涓涓帴鍙o紝浣犲彲浠ラ氳繃鍏朵粬鐨勫伐鍏枫佺紪绋嬭瑷鎴栬呮暟鎹簱妗嗘灦鏉ヨ闂暟鎹簱锛屽畠骞朵笉鏄壒瀹氫簬Django浣跨敤鐨勩

Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This work is licensed under the GNU Free Document License.
Hosting graciously provided by media temple
Chinese translate hosting by py3k.cn.