如我們所說,試圖負責邏輯和返回應答,例子中我們計算了當前的日期和時間
現在的Web程序中常常和數據庫打交道
一個數據庫驅動的網站在后臺連接數據庫服務器,得到并顯示很好的格式化的Web頁面
同樣,網站也可以提供給訪問者也具有操作數據庫的功能
許多復雜的網站以上兩種功能的結合,如Amazon.com就是一個數據庫驅動的站點
每一個產品頁面都是Amazon數據庫格式后的HTML,你訪問頁面也就是間接訪問數據庫
Django很適合數據庫驅動的網站,通過Python它提供強大的數據庫訪問能力
這章將講述Django的數據庫層
在視圖里進行數據庫查詢的“啞”方式
前一章講到通過在視圖里硬編碼HTML來輸出HTML的“啞”方式,在視圖里也有得到數據庫數據的“啞”方式
這很簡單,只是使用一些Python庫執行SQL查詢并且處理結果
在下面的例子里我們使用MySQLdb庫(可以在如下地址得到http://sourceforge.net/projects/mysql-python)
來連接MySQL數據庫,得到一些記錄來填充模板,并顯示到Web頁面上:
- from django.shortcuts import render_to_response
- import MySQLdb
- def book_list(request):
- db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
- cursor = db.cursor()
- cursor.execute('SELECT name FROM books ORDER BY name')
- names = [row[0] for row in cursor.fetchall()]
- db.close()
- return render_to_response('book_list.html', {'names': names})
這個方法可以工作,但是馬上一些問題出來了:
1,我們把數據庫連接的參數硬編碼到代碼里面了,理想狀況下它們應該存儲在Django配置里面
2,我們必須寫一些樣板文件代碼,如建立連接,創建cursor,執行語句和關閉連接等
細想狀況下,我們應該只需指出我們需要什么結果
3,它把我們和MySQL綁在一起,如果我們想切換到PostgreSQL
我們必須使用不同的數據庫適配器psycopg,改變數據庫連接參數以及考慮重寫SQL語句
理想狀況下數據庫服務器應該是抽象的,替換數據庫應該只在一個地方設置
你可能會想,Django的數據庫層的目標應該是解決這些問題,下面簡單看看怎樣用Django數據庫API重寫上面代碼:
- from django.shortcuts import render_to_response
- from mysite.books.models import Book
- def book_list(request):
- books = Book.objects.order_by('name')
- return render_to_response('book_list.html', {'books': books})
我們在本章稍后解釋這些代碼,現在先感覺一下它的樣子
MTV開發模式
在我們專研更多的代碼之前,讓我們先花點時間考慮一些Django Web程序的整體設計
前面的章節我們提到,Django設計來鼓勵松耦合和分離程序模塊
如果你遵循這個哲學,改變一部分代碼而不影響其它模塊是很容易做到的
例如在視圖方法里,我們討論了使用模板來分離業務邏輯和呈現邏輯的重要性
在數據庫層的數據訪問邏輯我們將遵循同樣的哲學
數據訪問,業務邏輯和呈現邏輯組成常說的“Model View Controller”(MVC)軟件架構模式
“Model”指數據訪問層,“View”指系統中選擇什么來呈現以及怎樣呈現的部分
“Controller”則指系統中通過用戶輸入決定使用哪個視圖及訪問必要的模型的部分
采用MVC,MTV等縮寫只是便于開發人員溝通
Django遵循了MVC模式,它可以被稱位MVC框架,下面是M,V,C在Django中的位置:
1,M,數據據訪問部分,通過Django的數據庫層處理,也就是本章所講述的內容
2,V,選擇數據并決定怎樣呈現的部分,通過視圖和模板來處理
3,C,控制部分通過Django框架本身的URL配置和對Python方法的調用來處理
因為“C”是Django框架本身處理而導致Django大部分精彩的東西在于模型,模板和視圖
所以Django被稱位MTV框架:
1,M,代表模型,是數據訪問層,它包含了關于數據的一切東西,怎樣得到數據,怎樣驗證數據,
它具有什么行為以及數據之間的關系
2,T,代表模板,是展現層,它包含了呈現相關的決策,如內容怎樣在Web頁面中顯示以及其它類型的文檔
3,V,代表視圖,是業務邏輯層,它包含了訪問模型的邏輯和選擇合適的模板
你可以認為視圖是模型和模板的橋梁
如果你對MVC框架熟悉,如Ruby on Rails,你可以把Django的視圖想象成“controllers”,
把Django的模板想象成“views”,這是對MVC的不同解釋造成的不幸的混亂
在Django關于MVC的解釋中,“view”描述呈現給用戶的數據
沒有必要弄清數據怎樣顯示,而是描述哪個數據應該被呈現
對比而言,Ruby on Rails以及類似的框架建議controller的工作包括決定哪個數據顯示給用戶,
視圖嚴格的決定數據怎樣顯示,而不是決定哪個數據來顯示
每一個解釋都不比另一個正確,最重要的事情是理解底層的概念
配置數據庫
所有的哲學牢記在心之后,讓我們開始發掘Django的數據庫層
首先我們注意一些細小的配置,我們需要告訴Django使用哪個數據庫和怎樣連接它
我們假設你已經有了一個數據庫服務器,啟動它并創建一個database(使用CREATE DATABASE語句)
SQLite是一個特例,不需要創建database,因為SQLite在文件系統上使用單獨的文件存儲數據
和上一章的TEMPLATE_DIRS一樣,數據庫配置在Django配置文件里面,默認是settings.py
- DATABASE_ENGINE = ''
- DATABASE_NAME = ''
- DATABASE_USER = ''
- DATABASE_PASSWORD = ''
- DATABASE_HOST = ''
- DATABASE_PORT = ''
我們來看看每個配置是什么意思:
1,DATABASE_ENGINE告訴Django使用哪個數據庫引擎,如果你使用數據庫和Django工作的話,
DATABASE_ENGINE必須是下面的字符串集合:
引用
設置 數據庫 需要的適配器
postgresql PostgreSQL psycopg version 1.x, http://initd.org/projects/psycopg1
postgresql_psycopg2 PostgreSQL psycopg version 2.x, http://initd.org/projects/psycopg2
mysql MySQL MySQLdb, http://sourceforge.net/projects/mysql-python
sqlite3 SQLite No adapter needed if using Python 2.5+ Otherwise, pysqlite, http://initd.org/tracker/pysqlite
ado_mssql Microsoft SQL Server adodbapi version 2.0.1+, http://adodbapi.sourceforge.net/
oracle Oracle cx_Oracle, http://www.python.net/crew/atuining/cx_Oracle/
注意不管你使用什么數據庫,你都需要安裝相應的數據庫適配器,每個適配器在網上都是免費的
2,DATABASE_NAME告訴Django數據庫名字是什么,如果你使用SQLite,
指出數據庫文件的完整的文件系統路徑,如'/home/django/mydata.db'
3,DATABASE_USER告訴Django你連接數據庫的用戶名,如果你使用SQLite,這項為空
4,DATABASE_PASSWORD告訴Django你連接數據庫的密碼,如果你使用SQLite或者你的密碼為空,則這項為空
5,DATABASE_HOST告訴Django你連接數據庫的主機,如果你的數據庫和Django安裝在同一臺計算機上,則這項為空
如果你使用SQLite,這項為空
MySQL在這里很特殊,如果這項的值以'/'開頭并且你使用MySQL,MySQL會通過Unix socket連接特殊的socket
例如DATABASE_HOST = '/var/run/mysql/'
如果你使用MySQL但這項的值不是以'/'開頭,那么這項的值就假設為所連接的主機
6,DATABASE_PORT告訴Django連接數據庫的端口,如果你使用SQLite,則這項為空
否則,如果這項為空,底層的數據庫適配器會使用給的數據庫的默認端口
大部分情況下默認端口即可
一旦你輸入了這項設置,測試一下你的配置
首先在你第2章創建的mysite項目目錄下運行python manage.py shell
你將會看到進入了Python交互環境,但是眼睛是會騙人的!
它和普通的python有一個重要的不同,普通的python命令進入的是Python shell,
但是前者告訴Django在啟動shell前使用哪個settings文件
這是做數據庫查詢的主要前提,Django需要知道使用哪個settings文件來得到數據庫連接信息
在后臺,python manage.py shell設置了DJANGO_SETTINGS_MODULE環境變量
后面我們會解釋它的微妙之處,先讓我們測試一下數據庫配置:
>>> from django.db import connnection
>>> cursor = connection.cursor()
如果什么事情都沒有發生,則你的數據庫配置對了
否則,檢查錯誤信息作為線索,看看哪里出錯了,下面是一些常見的錯誤:
- 錯誤信息 解決方法
- You haven’t set the DATABASE_ENGINE setting yet.
- 設置DATABASE_ENGINE而不是為空
- Environment variable DJANGO_SETTINGS_MODULE is undefined.
- 運行command python manage.py shell而不是python
- Error loading __ module: No module named __.
- 你還沒有安裝數據庫相關的適配器(如psycopg或MySQLdb)
- __ isn’t an available database backend.
- 將你的DATABASE_ENGINE設置為合法的數據庫引擎,你是不是敲錯字母了?
- database __ does not exist
- 更改DATABASE_NAME指向一個存在的數據庫,或者執行CREATE DATABASE語句來創建它
- role __ does not exist
- 更改DATABASE_USER指向一個存在的user,或者在數據庫中創建一個user
- could not connect to server
- 確認DATABASE_HOST和DATABASE_PORT設置正確,以及確認數據庫正在運行
你的第一個app
既然你驗證了數據庫連接正確,現在就來創建一個Django app
Django app是一些Django代碼,包括模型和視圖,它們在同一個Python包下面,代表了一個完整的Django程序
在這里值得解釋一下術語,因為這容易使初學者弄糊涂
我們第2章已經創建了一個project,那么project和app的區別是什么呢?區別就是配置和代碼:
1,一個project是許多Django app的集合的實例,加上那些app的的配置
技術上來說,一個project唯一的前提是它提供一個settings文件,里面定義了數據庫連接信息,
安裝的app,TEMPLATE_DIRS等等
2,一個app是Django的可移動功能集,通常包括模型和視圖,存在于一個單獨的Python包里面
例如,Django含有幾個app,如commenting系統和自動的admin界面
關鍵要注意的是它們是可移動并且可以在不同的project重用
沒有嚴格的規定怎樣安排和計劃你的Django代碼,它是很靈活的
如果你在構建一個單獨的網站,你可能只使用一個app
如果你在構建一個復雜的站點,你可能想把它分成幾個app,這樣你就可以在以后分別重用他們
在前面我們的例子中證明我們確實根本不需要創建app,我們只是創建了一個viws.py文件
然后在里面寫視圖方法并設置我們的URL配置指向這些方法,我們不需要“apps”
但是,有一點需要重視app慣例,如果你使用Django的數據庫層(模型),你必須創建Django app
模型必須存在于app,所以為了開始寫模型,我們將創建一個新的app
在前面創建的mysite目錄下面,運行下面的命令來創建一個新的app:
python manage.py startapp books
這個命令不會造成任何輸出,但它在mysite目錄下創建了一個books目錄,讓我們看看它的內容:
books/
__init__.py
models.py
views.py
這些文件將包含這個app的模型和視圖
用你最喜歡的文本編輯器看看models.py和views.py,它們都是空的,除了models.py里一個import
這是你的Django app的空白區
用Python定義模型
我們前面討論到,MTV中的M代表模型
一個Django模型用Python代碼描述了你的數據庫中的數據
它是你的數據結構,相當于SQL的CREATE TABLE語句,除了在Python中它比數據庫定義包含的內容更多
Django在后臺使用模型來執行SQL代碼并返回方便的Python數據結構來表示你的數據庫表的行
Django也使用模型來描述一些高級概念,這些SQL是做不到的
如果你對數據庫很熟悉,你可能馬上會想到既在Python中又在SQL中定義數據模型豈不是很多余?
Django采用這種工作方式有幾個原因:
1,自省要求過度并且不完美
為了提供方便的數據訪問API,Django需要知道數據庫結構,有兩種方式達到這個目標
一是在Python里顯式的描述數據,一是運行時內省數據庫來決定數據模型
第二種方式看起來更干凈,因為表的元數據僅僅存在于一個地方,但這會導致幾個問題
第一,運行時內省數據庫顯然要求過度
如果每次Web請求都需要內省數據庫,即使Web服務器已經初始化,這也會導致的過度的等級不可接受
(有些人認為這個過度的等級可以接受,但Django的開發者目標是打敗盡可能多的過度框架,
所以這個方案使Django成功的在速度上快于其它的高級框架)第二,一些數據庫特別是舊版本的MySQL
并不把足夠的元數據存儲起來,所以就導致不能進行準確和完整的自省
2,寫Python代碼是快樂的,保持所有的事情用Python來做可以減少你大腦作切換的時間
如果你保持一個單獨的開發環境和心智盡可能久,它將是你非常的高效
寫SQL,然后Python,然后又SQL是很令人心煩的
3,讓數據模型存儲在代碼里而不是你的數據庫會使你更容易控制你的模型版本
這樣你可以很輕松的跟蹤你的數據的更改
4,SQL僅僅允許關于數據結構的某一級別的元數據
例如,大部分數據庫系統并不提供專門的數據類型來支持e-mail地址或者url
Django模型則可以,高級數據類型的優點是更高的生產率和更易重用的代碼
5,SQL在不同的數據庫平臺不一致,例如,如果你正在發布你一個Web程序
發布一個Python模塊來描述數據結構會比分開為MySQL,PostgreSQL和SQLite寫CREATE TABLE語句更高效
盡管如此,這個方法的一個缺點是Python代碼所做的事情可能超出實際上數據庫里的數據的范圍
如果你更改了Django模型,你需要在你的數據庫做同樣的改動做保持數據庫和模型一致
本章后面我們將詳細解釋解決此問題的策略
最后,我們必須指出的是Django包含了一個輔助工具來通過現存的數據庫生成模型
這對于迅速接管和運行遺留數據很有幫助
你的第一個模型
這一章我們將關注book/author/publisher數據結構,它們是眾所周知的
我們將支持一下概念,域和關系:
1,一個author有一個salutation(如Mr.或Mrs.),一個first name,一個last name,一個e-mail地址和一個頭像photo
2,一個publisher有一個name,一個street地址,一個city,一個state/province,一個country和一個Web site
3,一個book有一個title和一個publication date,一個或多個authors(many-to-many),一個單獨的publisher(one-to-many)
在Django中第一步是使用Python代碼描述上面的數據庫結構,在startapp命令創建的models.py中輸入下面的內容:
- from django.db import models
- class Publisher(models.Model):
- name = models.CharField(maxlength=30)
- address = models.CharField(maxlength=50)
- city = models.CharField(maxlength=60)
- state_province = models.CharField(maxlength=30)
- country = models.CharField(maxlength=50)
- website = models.URLField()
- class Author(models.Model):
- salutation = models.CharField(maxlength=10)
- first_name = models.CharField(maxlength=30)
- last_name = models.CharField(maxlength=40)
- email = models.EmailField()
- headshot = models.ImageField(upload_to='/tmp')
- class Book(models.Model):
- title = models.CharField(maxlength=100)
- authors = models.ManyToManyField(Author)
- publisher = models.ForeignKey(Publisher)
- publication_date = models.DateField()
這章我們會談到模型語法和選項,讓我們先來快速的看看這些代碼來得到基本的印象
要注意的第一點是每個模型都是django.db.models.Model的子類
它們的父類Model包含了讓這些對象具有與數據庫交互能力的機制
這樣一來我們的模型只負責定義自己的域就行了,語法相當簡潔緊湊
不管相信與否,這就是通過Django進行數據訪問的所有代碼
一個模型通常域一個數據庫表對應,而每個屬性和數據庫表的一列對應
屬性名對應列名,屬性的類型(如CharField)對應數據庫列類型
例如Publisher模型對應了下面的表(假設使用PostgreSQL的CREATE TABLE語法):
- CREATE TABLE "books_publisher" (
- "id" serial NOT NULL PRIMARY KEY,
- "name" varchar(30) NOT NULL,
- "address" varchar(50) NOT NULL,
- "city" varchar(60) NOT NULL,
- "state_province" varchar(30) NOT NULL,
- "country" varchar(50) NOT NULL,
- "website" varchar(200) NOT NULL
- );
事實上Django自己可以生成CREAT TABLE語句,我們一會再看
一個類對應一個數據庫表的特例是多對多關系,我們的例子中Book有一個ManyToManyField叫作authors
這表明book擁有一個或多個authors,但是Book表并沒有authors列
Django創建了一個附加的多對多連接表來處理books到authors的映射
最后注意的是我們沒有在任何一個模型中顯示的定義主鍵
除非你自己定義一個主鍵,Django會自動為每個模型生成一個integer主鍵域id
每個Django模型都必須有一個單列的主鍵
安裝模型
寫完代碼,下面讓我們來創建數據庫表
第一步是在Django中激活這些模型,需要把books這個app添加到settings文件的apps列表
編輯settings.py,查找INSTALLED_APPS設置
INSTALLED_APPS告訴Django哪些apps是活動的,默認時如下所示:
- INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- )
先用(#)把這些strings注釋掉,后面我們再激活和討論它們
然后添加'mysite.books'到INSTALLED_APPS列表,最后如下所示:
- INSTALLED_APPS = (
- #'django.contrib.auth',
- #'django.contrib.contenttypes',
- #'django.contrib.sessions',
- #'django.contrib.sites',
- 'mysite.books',
- )
別忘了最后的逗號
順便說一下,本書作者習慣與在元組的元素后面都加上逗號,無論元組是否只有一個元素
這可以避免忘記加逗號,加了也不會罰款
'mysite.books'指我們正在工作的books app
INSTALLED_APPS中的每個app都用完整的Python PATH來表示,即包的PATH,用小數點分隔來指向app包
Django app已經在settings文件激活,我們可以在數據庫中創建表了
首先通過如下的命令驗證一下模型:python manage.py validate
validate命令檢查我們的模型語法和邏輯正確與否
如果一切正常,我們會看到0 errors found的信息
否則,確認你的模型代碼輸入正確,error輸出會給你有用的信息來幫你找到錯誤的代碼
任何時候你認為你的模型代碼有問題都可以運行python manage.py validate來捕捉模型錯誤
如果你的模型是合法的,運行下面的命令為books app的模型生成CREATE TABLE語句
(如果你使用Unix會有五顏六色的語法高亮):python manage.py sqlall books
這個命令中,books是app的名字,運行完命令,你會看到下面的信息:
- BEGIN;
- CREATE TABLE "books_publisher" (
- "id" serial NOT NULL PRIMARY KEY,
- "name" varchar(30) NOT NULL,
- "address" varchar(50) NOT NULL,
- "city" varchar(60) NOT NULL,
- "state_province" varchar(30) NOT NULL,
- "country" varchar(50) NOT NULL,
- "website" varchar(200) NOT NULL
- );
- CREATE TABLE "books_book" (
- "id" serial NOT NULL PRIMARY KEY,
- "title" varchar(100) NOT NULL,
- "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
- "publication_date" date NOT NULL
- );
- CREATE TABLE "books_author" (
- "id" serial NOT NULL PRIMARY KEY,
- "salutation" varchar(10) NOT NULL,
- "first_name" varchar(30) NOT NULL,
- "last_name" varchar(40) NOT NULL,
- "email" varchar(75) NOT NULL,
- "headshot" varchar(100) NOT NULL
- );
- CREATE TABLE "books_book_authors" (
- "id" serial NOT NULL PRIMARY KEY,
- "book_id" integer NOT NULL REFERENCES "books_book" ("id"),
- "author_id" integer NOT NULL REFERENCES "books_author" ("id"),
- UNIQUE ("book_id", "author_id")
- );
- CREATE INDEX books_book_publisher_id ON "books_book" ("publisher_id");
- COMMIT;
注意以下幾點:
1,表明自動由app名(books)和小寫的模型名-publisher,book和author組成
你可以覆蓋這個行為,我們本章后面會看到
2,前面提到,Django自動給每個表添加主鍵id域,你也可以覆蓋這點
3,習慣約束上Django會在外鍵域的名字后面添加“_id”,你已經猜到了,你也可以覆蓋這點
4,外鍵關系由顯式的REFERENCES語句來完成
5,這些CREATE TABLE語句是針對你使用的數據庫生成的,所以數據庫專有的域類型如
aotu_increment(MySQL),serial(PostgreSQL),或者integer primary key(SQLite)會自動為你處理
類似的如表名的引號是使用單引號還是雙引號也一樣,這個例子是使用的PostgreSQL語法
sqlall命令事實上并沒有接觸數據庫或建表,它僅僅將輸出打印到屏幕上
所以如果你問它,你可以看到DJango將執行什么
如果你愿意,你可以復制粘貼這些SQL到你數據庫客戶端或者使用Unix管道來直接傳遞它
盡管如此,Django提供一個簡單的方式來把這些SQL提交數據庫
像下面這樣運行syncdb命令:python manage.py syncdb
你會看到如下信息:
Creating table books_publisher
Creating table books_book
Creating table books_author
Installing index for books.Book model
syncdb簡單的把你的模型同步到數據庫
它檢查數據庫和你的INSTALLED_APPS中的所有app的所以模型,看看是否有些表已經存在,如果表不存在就創建表
注意syncdb不會同步改動或刪除了的模型,如果你改動或刪除了一個模型,syncdb不會更新數據庫(待會兒討論這個)
如果你再運行一次python manage.py syncdb,不會發生任何事情
因為你沒有添加模型到books app或添加到INSTALLED_APPS中的任何app
因此運行python manage.py syncdb是一直安全的,它不會把事情弄糟
如果你感興趣,進入你的數據庫服務器的命令行客戶端看看Django創建的數據庫表
你可以手動運行命令行客戶端如PostgreSQL的psql,或者運行python manage.py dbshell
基于你的DATABASE_SERVER設置,后者將計算出運行哪個命令行客戶端,也更方便
數據訪問基礎
一旦你創建了一個模型,Django自動提供高級Python API給這些模型工作
運行python manage.py shell然后輸入下面的代碼試試:
- >>> from books.models import Publisher
- >>> p = Publisher(name='Apress', address='2560 Ninth St.',
- ... city='Berkeley', state_province='CA', country='U.S.A.',
- ... website='http://www.apress.com/')
- >>> p.save()
- >>> p = Publisher(name="O'Reilly", address='10 Fawcett St.',
- ... city='Cambridge', state_province='MA', country='U.S.A.',
- ... website='http://www.oreilly.com/')
- >>> p.save()
- >>> publisher_list = Publisher.objects.all()
- >>> publisher_list
- [<Publisher: Publisher object>, <Publisher: Publisher object>]
雖然只有幾行代碼,確達到了很多目的,精彩的部分是:
1,創建一個對象只需import合適的模型類并通過給每個域傳遞值來初始化它
2,調用save()方法來將一個對象保存到數據庫,后臺Django在這里執行了一條INSERT SQL語句
3,使用Publisher.objects屬性從數據庫得到對象,使用Publisher.objects.all()得到Publisher所有的對象列表
后臺Django在這里執行了一條SELECT SQL語句
實際上你可以通過Django數據庫API做很多事情,但是我們先來看一個小麻煩
添加模型的string顯示
上面的例子中,當我們打印publishers列表時我們得到的都是一些無用的信息,我們很難將Publisher對象區別開:
[<Publisher: Publisher object>, <Publisher: Publisher object>]
我們可以通過給Publisher對象添加一個__str__()方法來輕松解決這個問題
__str__()方法告訴Python怎樣顯示對象的string顯示,你可以動手來看看給三個模型添加__str__():
- class Publisher(models.Model):
- name = models.CharField(maxlength=30)
- address = models.CharField(maxlength=50)
- city = models.CharField(maxlength=60)
- state_province = models.CharField(maxlength=30)
- country = models.CharField(maxlength=50)
- website = models.URLField()
- def __str__(self):
- return self.name
- class Author(models.Model):
- salutation = models.CharField(maxlength=10)
- first_name = models.CharField(maxlength=30)
- last_name = models.CharField(maxlength=40)
- email = models.EmailField()
- headshot = models.ImageField(upload_to='/tmp')
- def __str__(self):
- return '%s %s' % (self.first_name, self.last_name)
- class Book(models.Model):
- title = models.CharField(maxlength=100)
- authors = models.ManyToManyField(Author)
- publisher = models.ForeignKey(Publisher)
- publication_date = models.DateField()
- def __str__(self):
- return self.title
你可以看到,__str__()方法為了返回一個string顯示可以做任何它需要做的事情
這里Publisher和Book的__str__()方法簡單的返回了對象的name和title
但是Author的__str__()更復雜一點,返回了first_name和last_name的組合
__str__()唯一的條件是返回一個string,如果不返回string的話如返回一個integer
Python會觸發一個TypeError異常,并帶有“__str__ returned non-string”信息
為了讓改動生效,退出Python然后使用python manage.py shell命令重新進入
(這是讓代碼改動生效的最簡單的方式)
現在,Publisher列表對象更容易理解:
- >>> from books.models import Publisher
- >>> publisher_list = Publisher.objects.all()
- >>> publisher_list
- [<Publisher: Apress>, <Publisher: O'Reilly>]
確認你定義的任何模型都有一個__str__()方法,不僅是使在你自己使用交互環境時更方便
也因為當Django在幾個地方需要顯示對象時會使用__str__()的輸出
最后,注意__str__()是給模型添加行為的好習慣
一個Django模型描述的不僅僅是一個對象數據庫表結構,它也描述了對象知道怎樣去做的功能
__str__()就是這樣的功能的一個例子,一個模型知道怎樣顯示它自己
安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢】