亚洲成人一区在线观看_天堂网www_国产精品久久9_中文在线播放_伊人天天_久久精品久久久精品美女

當前位置:首頁 > 網站舊欄目 > 學習園地 > 設計軟件教程 > 翻譯www.djangobook.com之第五章:與數據庫交互:模型

翻譯www.djangobook.com之第五章:與數據庫交互:模型
2010-01-13 23:36:18  作者:  來源:
第3章我們談到了用Django構建動態網站,設置視圖和URL配置
如我們所說,試圖負責邏輯和返回應答,例子中我們計算了當前的日期和時間
現在的Web程序中常常和數據庫打交道
一個數據庫驅動的網站在后臺連接數據庫服務器,得到并顯示很好的格式化的Web頁面
同樣,網站也可以提供給訪問者也具有操作數據庫的功能
許多復雜的網站以上兩種功能的結合,如Amazon.com就是一個數據庫驅動的站點
每一個產品頁面都是Amazon數據庫格式后的HTML,你訪問頁面也就是間接訪問數據庫
Django很適合數據庫驅動的網站,通過Python它提供強大的數據庫訪問能力
這章將講述Django的數據庫層

在視圖里進行數據庫查詢的“啞”方式
前一章講到通過在視圖里硬編碼HTML來輸出HTML的“啞”方式,在視圖里也有得到數據庫數據的“啞”方式
這很簡單,只是使用一些Python庫執行SQL查詢并且處理結果
在下面的例子里我們使用MySQLdb庫(可以在如下地址得到http://sourceforge.net/projects/mysql-python)
來連接MySQL數據庫,得到一些記錄來填充模板,并顯示到Web頁面上:
Java代碼 復制代碼
  1. from django.shortcuts import render_to_response   
  2. import MySQLdb   
  3.   
  4. def book_list(request):   
  5.     db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')   
  6.     cursor = db.cursor()   
  7.     cursor.execute('SELECT name FROM books ORDER BY name')   
  8.     names = [row[0for row in cursor.fetchall()]   
  9.     db.close()   
  10.     return render_to_response('book_list.html', {'names': names})  

這個方法可以工作,但是馬上一些問題出來了:
1,我們把數據庫連接的參數硬編碼到代碼里面了,理想狀況下它們應該存儲在Django配置里面
2,我們必須寫一些樣板文件代碼,如建立連接,創建cursor,執行語句和關閉連接等
細想狀況下,我們應該只需指出我們需要什么結果
3,它把我們和MySQL綁在一起,如果我們想切換到PostgreSQL
我們必須使用不同的數據庫適配器psycopg,改變數據庫連接參數以及考慮重寫SQL語句
理想狀況下數據庫服務器應該是抽象的,替換數據庫應該只在一個地方設置
你可能會想,Django的數據庫層的目標應該是解決這些問題,下面簡單看看怎樣用Django數據庫API重寫上面代碼:
Java代碼 復制代碼
  1. from django.shortcuts import render_to_response   
  2. from mysite.books.models import Book   
  3.   
  4. def book_list(request):   
  5.     books = Book.objects.order_by('name')   
  6.     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
Java代碼 復制代碼
  1. DATABASE_ENGINE = ''  
  2. DATABASE_NAME = ''  
  3. DATABASE_USER = ''  
  4. DATABASE_PASSWORD = ''  
  5. DATABASE_HOST = ''  
  6. 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()
如果什么事情都沒有發生,則你的數據庫配置對了
否則,檢查錯誤信息作為線索,看看哪里出錯了,下面是一些常見的錯誤:
Java代碼 復制代碼
  1. 錯誤信息                                                    解決方法    
  2. You haven’t set the DATABASE_ENGINE setting yet.   
  3. 設置DATABASE_ENGINE而不是為空   
  4.   
  5. Environment variable DJANGO_SETTINGS_MODULE is undefined.   
  6. 運行command python manage.py shell而不是python   
  7.   
  8. Error loading __ module: No module named __.   
  9. 你還沒有安裝數據庫相關的適配器(如psycopg或MySQLdb)   
  10.   
  11. __ isn’t an available database backend.   
  12. 將你的DATABASE_ENGINE設置為合法的數據庫引擎,你是不是敲錯字母了?   
  13.   
  14. database __ does not exist   
  15. 更改DATABASE_NAME指向一個存在的數據庫,或者執行CREATE DATABASE語句來創建它   
  16.   
  17. role __ does not exist   
  18. 更改DATABASE_USER指向一個存在的user,或者在數據庫中創建一個user   
  19.   
  20. could not connect to server   
  21. 確認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中輸入下面的內容:
Java代碼 復制代碼
  1. from django.db import models   
  2.   
  3. class Publisher(models.Model):   
  4.     name = models.CharField(maxlength=30)   
  5.     address = models.CharField(maxlength=50)   
  6.     city = models.CharField(maxlength=60)   
  7.     state_province = models.CharField(maxlength=30)   
  8.     country = models.CharField(maxlength=50)   
  9.     website = models.URLField()   
  10.   
  11. class Author(models.Model):   
  12.     salutation = models.CharField(maxlength=10)   
  13.     first_name = models.CharField(maxlength=30)   
  14.     last_name = models.CharField(maxlength=40)   
  15.     email = models.EmailField()   
  16.     headshot = models.ImageField(upload_to='/tmp')   
  17.   
  18. class Book(models.Model):   
  19.     title = models.CharField(maxlength=100)   
  20.     authors = models.ManyToManyField(Author)   
  21.     publisher = models.ForeignKey(Publisher)   
  22.     publication_date = models.DateField()  

這章我們會談到模型語法和選項,讓我們先來快速的看看這些代碼來得到基本的印象
要注意的第一點是每個模型都是django.db.models.Model的子類
它們的父類Model包含了讓這些對象具有與數據庫交互能力的機制
這樣一來我們的模型只負責定義自己的域就行了,語法相當簡潔緊湊
不管相信與否,這就是通過Django進行數據訪問的所有代碼
一個模型通常域一個數據庫表對應,而每個屬性和數據庫表的一列對應
屬性名對應列名,屬性的類型(如CharField)對應數據庫列類型
例如Publisher模型對應了下面的表(假設使用PostgreSQL的CREATE TABLE語法):
Java代碼 復制代碼
  1. CREATE TABLE "books_publisher" (   
  2.     "id" serial NOT NULL PRIMARY KEY,   
  3.     "name" varchar(30) NOT NULL,   
  4.     "address" varchar(50) NOT NULL,   
  5.     "city" varchar(60) NOT NULL,   
  6.     "state_province" varchar(30) NOT NULL,   
  7.     "country" varchar(50) NOT NULL,   
  8.     "website" varchar(200) NOT NULL   
  9. );  

事實上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是活動的,默認時如下所示:
Java代碼 復制代碼
  1. INSTALLED_APPS = (   
  2.     'django.contrib.auth',   
  3.     'django.contrib.contenttypes',   
  4.     'django.contrib.sessions',   
  5.     'django.contrib.sites',   
  6. )  

先用(#)把這些strings注釋掉,后面我們再激活和討論它們
然后添加'mysite.books'到INSTALLED_APPS列表,最后如下所示:
Java代碼 復制代碼
  1. INSTALLED_APPS = (   
  2.     #'django.contrib.auth',   
  3.     #'django.contrib.contenttypes',   
  4.     #'django.contrib.sessions',   
  5.     #'django.contrib.sites',   
  6.     'mysite.books',   
  7. )  

別忘了最后的逗號
順便說一下,本書作者習慣與在元組的元素后面都加上逗號,無論元組是否只有一個元素
這可以避免忘記加逗號,加了也不會罰款
'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的名字,運行完命令,你會看到下面的信息:
Java代碼 復制代碼
  1. BEGIN;   
  2. CREATE TABLE "books_publisher" (   
  3.     "id" serial NOT NULL PRIMARY KEY,   
  4.     "name" varchar(30) NOT NULL,   
  5.     "address" varchar(50) NOT NULL,   
  6.     "city" varchar(60) NOT NULL,   
  7.     "state_province" varchar(30) NOT NULL,   
  8.     "country" varchar(50) NOT NULL,   
  9.     "website" varchar(200) NOT NULL   
  10. );   
  11. CREATE TABLE "books_book" (   
  12.     "id" serial NOT NULL PRIMARY KEY,   
  13.     "title" varchar(100) NOT NULL,   
  14.     "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),   
  15.     "publication_date" date NOT NULL   
  16. );   
  17. CREATE TABLE "books_author" (   
  18.     "id" serial NOT NULL PRIMARY KEY,   
  19.     "salutation" varchar(10) NOT NULL,   
  20.     "first_name" varchar(30) NOT NULL,   
  21.     "last_name" varchar(40) NOT NULL,   
  22.     "email" varchar(75) NOT NULL,   
  23.     "headshot" varchar(100) NOT NULL   
  24. );   
  25. CREATE TABLE "books_book_authors" (   
  26.     "id" serial NOT NULL PRIMARY KEY,   
  27.     "book_id" integer NOT NULL REFERENCES "books_book" ("id"),   
  28.     "author_id" integer NOT NULL REFERENCES "books_author" ("id"),   
  29.     UNIQUE ("book_id""author_id")   
  30. );   
  31. CREATE INDEX books_book_publisher_id ON "books_book" ("publisher_id");   
  32. 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然后輸入下面的代碼試試:
Java代碼 復制代碼
  1. >>> from books.models import Publisher   
  2. >>> p = Publisher(name='Apress', address='2560 Ninth St.',   
  3. ...     city='Berkeley', state_province='CA', country='U.S.A.',   
  4. ...     website='http://www.apress.com/')   
  5. >>> p.save()   
  6. >>> p = Publisher(name="O'Reilly", address='10 Fawcett St.',   
  7. ...     city='Cambridge', state_province='MA', country='U.S.A.',   
  8. ...     website='http://www.oreilly.com/')   
  9. >>> p.save()   
  10. >>> publisher_list = Publisher.objects.all()   
  11. >>> publisher_list   
  12. [<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__():
Java代碼 復制代碼
  1. class Publisher(models.Model):   
  2.     name = models.CharField(maxlength=30)   
  3.     address = models.CharField(maxlength=50)   
  4.     city = models.CharField(maxlength=60)   
  5.     state_province = models.CharField(maxlength=30)   
  6.     country = models.CharField(maxlength=50)   
  7.     website = models.URLField()   
  8.   
  9.     def __str__(self):   
  10.         return self.name   
  11.   
  12. class Author(models.Model):   
  13.     salutation = models.CharField(maxlength=10)   
  14.     first_name = models.CharField(maxlength=30)   
  15.     last_name = models.CharField(maxlength=40)   
  16.     email = models.EmailField()   
  17.     headshot = models.ImageField(upload_to='/tmp')   
  18.   
  19.     def __str__(self):   
  20.         return '%s %s' % (self.first_name, self.last_name)   
  21.   
  22. class Book(models.Model):   
  23.     title = models.CharField(maxlength=100)   
  24.     authors = models.ManyToManyField(Author)   
  25.     publisher = models.ForeignKey(Publisher)   
  26.     publication_date = models.DateField()   
  27.   
  28.     def __str__(self):   
  29.         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列表對象更容易理解:
Java代碼 復制代碼
  1. >>> from books.models import Publisher   
  2. >>> publisher_list = Publisher.objects.all()   
  3. >>> publisher_list   
  4. [<Publisher: Apress>, <Publisher: O'Reilly>]  

確認你定義的任何模型都有一個__str__()方法,不僅是使在你自己使用交互環境時更方便
也因為當Django在幾個地方需要顯示對象時會使用__str__()的輸出
最后,注意__str__()是給模型添加行為的好習慣
一個Django模型描述的不僅僅是一個對象數據庫表結構,它也描述了對象知道怎樣去做的功能
__str__()就是這樣的功能的一個例子,一個模型知道怎樣顯示它自己


安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢
主站蜘蛛池模板: 午夜精品影院 | 免费毛片在线播放 | 射久久 | 亚洲天堂男人 | 嫩草懂你 | 91精品国产91久久久久游泳池 | 成人精品一区二区三区 | 日韩成人在线一区 | 亚洲免费成人av | 欧美成人激情视频 | 午夜影皖 | 久久1区 | 91精品国产综合久久久久久漫画 | 久久久久久人 | 91久久极品 | 欧美伦理电影一区二区 | 国产一区二区三区在线看 | 91网在线播放 | 日日骑夜夜操 | 91精品国产91久久久久久不卡 | 欧美日韩在线视频一区 | 精品1区 | 久久久久久久av | 成人免费视频网站在线观看 | 午夜寂寞影视在线观看 | a级毛片免费高清视频 | 九九热这里只有精品在线观看 | 日韩一区二区精品 | 国产中文字幕在线 | 中文字幕一区二区三区乱码图片 | 国产精品自拍视频 | 九九九视频精品 | 亚洲a在线观看 | 91福利网站在线观看 | 久久精品黄 | 精品国产一区二区三区久久久蜜 | 日韩午夜免费 | 亚洲精品电影在线一区 | 欧美78videosex性欧美 | 日本韩国欧美一区 | 国产美女网站视频 | 九九热在线免费视频 | 天天插天天操天天干 | 国内精品视频在线观看 | 精品国产一区二区三区成人影院 | √8天堂资源地址中文在线 成人欧美一区二区三区白人 | 国产精品久久久久国产a级 国产精品欧美一区二区三区不卡 | 欧美一级艳情片免费观看 | 久久福利 | 国产一级视频在线观看 | 日韩在线精品 | 日韩免费在线视频 | 国产亚洲欧美精品永久 | 一区二区三区视频 | 热re99久久精品国99热线看 | 亚洲高清视频一区二区三区 | 日韩免费网站 | 激情五月婷婷在线 | 成人欧美一区二区三区 | 欧美一区二区三区在线视频观看 | 日本一级毛片视频 | 久久成人免费观看 | 99国产精品99久久久久久 | 国产精品久久久久久久免费大片 | 成人午夜在线视频 | 亚洲美女一区二区三区 | 中文字幕亚洲区 | 亚洲精品国产第一综合99久久 | 日韩中文字幕一区二区 | 精品中文字幕在线观看 | 在线视频一区二区 | 午夜视频在线观看网站 | 可以在线观看的黄色 | 成人午夜精品 | 国产亚洲一区二区三区 | 日韩精品久久 | 精品国产一区二区三区在线观看 | 久久久亚洲 | 精品国产一区二区三区免费 | av大片网 | 羞羞的视频在线免费观看 | 99热精品在线 | 久久精品一区二区三区四区 | 国产免费av大片 | 国产激情视频在线观看 | 日本妇乱大交xxxxx | 干干干操操操 | 亚洲精品视频在线 | 天天干天天操天天干 | 国产精国产精品 | 亚洲欧美日韩另类精品一区二区三区 | 久久亚洲一区 | 黄色片免费在线观看视频 | 超碰人人爱 | 亚洲在线 | 97精品久久 | 精品日韩 | 国产精品不卡 | 国产片侵犯亲女视频播放 | 不卡一区二区三区四区 | 欧美一区二区三区免费 | 久久久久久成人 | 国产精品一区二区三区在线播放 | 亚洲一区二区福利 | 欧美成人一区二区三区 | 亚洲精品中文字幕中文字幕 | 成人1区| 欧美电影一区 | 久久网一区二区三区 | 免费毛片视频 | 国产精品不卡视频 | 成年人在线视频播放 | 99精品热| 中文字幕亚洲综合 | 在线观看91 | 国产精品毛片一区二区三区 | 一本大道综合伊人精品热热 | 亚洲精品综合 | 天天拍天天草 | 久久精品国产99国产精品 | 欧美精品一区二区三区在线四季 | 亚洲人成人一区二区在线观看 | 特黄特黄aaaa级毛片免费看 | 午夜激情av | 色免费在线观看 | 久久精av | 欧美日韩中文在线观看 | 亚洲另类视频 | 91.xxx.高清在线 | 影视在线观看 | 久久人人爽人人爽人人片亚洲 | 国产福利视频在线观看 | 99精品免费视频 | 日韩亚洲欧美综合 | 一级毛片免费网站 | 美女福利视频网站 | 色站综合| 日韩欧美二区 | 成人一区二区在线 | 久久免费视频3 | 天天插天天干 | 天天操网 | 日韩免费一区二区 | 欧美狠狠操| 日韩成人在线视频 | 2012中文版免费观看 | 午夜精品久久 | 久久久久久久 | 日韩欧美在线一区二区 | 日韩一区欧美 | 一区二区三区精品视频 | 自拍偷拍小视频 | 国产在线观看免费 | 日本不卡高字幕在线2019 | 一区二区三区高清 | 国产精品一区二区在线看 | 亚洲天堂男人 | 亚洲福利国产 | 日韩中文一区二区三区 | 999在线观看精品免费不卡网站 | 国产精品一区二区三区在线 | 最新av网址大全 | 热久久免费视频 | 国产精品一二 | 91麻豆精品国产91久久久久久久久 | 五月色综合 | 亚洲电影在线看 | 亚洲网站免费看 | 人人爽视频| 老司机深夜福利视频 | 99精品全国免费观看视频软件 | 欧美中文字幕一区二区 | 91久久久久久 | 欧美一级免费播放 | 精品二区 | 夜夜爽99久久国产综合精品女不卡 | 在线免费视频成人 | 91黄色免费看 | 亚洲一区二区在线免费观看 | 欧美日韩精品一区二区在线播放 | 亚洲激情综合 | 在线中文字幕av | 亚洲精品18 | 亚洲欧洲精品成人久久奇米网 | 久99视频| 亚州男人天堂 | 亚洲一区av在线 | 国产一级片a | 91免费看| 先锋资源久久 | 欧美日韩一区在线 | 成人国产精品视频 | 亚洲xx在线 | 三级特黄特色视频 | 国产在线观看免费av | 久久九精品 | 久久一二| 国产精品原创巨作av | 日韩免费网站 | 中文字幕一级 | 欧美久久久久久久久久久 | 91精品久久久久久久91蜜桃 | 午夜国产精品视频 | 久久久99精品免费观看 | 一本一道久久久a久久久精品91 | 亚洲电影在线观看 | 毛片aaa| 色婷婷亚洲一区二区三区 | 久久久午夜爽爽一区二区三区三州 | 日干夜操 | 日韩在线观看一区二区 | 亚洲电影一区 | 一区二区三区视频免费看 | 91精品国产综合久久婷婷香蕉 | 综合二区 | 亚洲成人福利在线观看 | 日韩视频一区二区三区 | 91免费看片 | av大片| 久久这里只有国产精品 | 黄色大片在线播放 | 国产精品一二三区 | 夜夜草视频 | 九九人人| 黄色影视在线免费观看 | 久久综合久久综合久久 | 久久久99国产精品免费 | 欧美日韩中文在线观看 | 免费黄色片在线观看 | 欧美在线综合视频 | 亚洲精品国产精品国自产 | 国产在线中文字幕 | 亚洲成人一区二区三区 | 中文字幕一区二区三区在线视频 | 91啪影院 | 国产午夜久久久久 | 国产成人免费视频网站视频社区 | 亚洲欧美日韩电影 | 亚洲日本二区 | 欧美日韩最新 | 色黄视频在线观看 | 性欧美精品高清 | 亚洲国产一区二区三区四区 | 国产精品久久久久久久久久久久冷 | 国产伦精品一区二区三区四区视频 | 国产欧美在线 | 在线中文视频 | 亚洲精品久久一区二区三区 | 成人免费视频网站在线观看 | 成人在线精品视频 | 99久久精品国产一区二区三区 | 99热国产在线观看 | 极品女神高潮呻吟av久久 | 青青久在线视频 | 一区二区观看 | 国产一区久久久 | 欧美在线视频一区二区 | 麻豆视频91 | 精品人伦一区二区三区蜜桃视频 | 日韩视频一区二区三区 | avmans最新导航地址 | 99久久婷婷国产综合精品 | 亚洲三级av| 台湾av在线 | 亚洲成人第一 | 一区| 吊视频一区二区三区 | 玖玖视频在线 | 999精品网 | 亚洲免费网 | 97伦理网 | 中文字幕视频网站 | 日韩中文字幕免费视频 | 香蕉大人久久国产成人av | 日本妇人成熟免费视频 | 欧美一级高清在线 | 亚洲精品视频在线播放 | 亚洲永久免费 | 精品久久久久久久久久久久久久 | 成人精品鲁一区一区二区 | 视频一区二区三区免费观看 | 久久99精品久久久水蜜桃 | 亚洲国产成人在线观看 | 久久免费国产精品 | 日一区二区| 91在线精品视频 | 亚洲精品福利在线 | 福利午夜 | 男女羞羞视频网站18 | 欧美a√ | 欧美伦理一区二区 | 国产福利91精品一区二区 | 午夜在线小视频 | 精品一区二区三 | www精品美女久久久tv | 99精品欧美一区二区三区 | 性色av一区二区三区 | 日韩成人在线视频 | 天天干夜夜爽 | 精品国产乱码久久久久久1区2区 | 成人激情免费视频 | 亚洲欧洲tv | 国产麻豆一区二区三区 | 伊人春色网| 亚洲综合电影 | 国产精品婷婷午夜在线观看 | 日av一区 | 日韩一级电影在线 | 午夜在线影院 | 在线免费观看成年人视频 | 三级av网站 | 欧美一区2区三区3区公司 | 日韩午夜电影 | 久久久久国产一区二区三区 | 成人国产综合 | youjizz国产| 国产电影一区二区在线观看 | 亚洲天堂第一页 | 91视频国内 | 国产一级影片 | 午夜影院网站 | 超碰国产在线 | 国产精品一区二区免费 | 精品久久久成人 | 国产精品九九久久99视频 | 婷婷五月色综合香五月 | 午夜影院久久 | av影片在线播放 | 三区影院| a级在线观看免费 | 欧美日本高清视频 | 黄色大片在线播放 | 91免费看片 | 这里有精品视频 | 国产精品久久久久久久久软件 | 在线看片日韩 | 91观看在线视频 | 日韩精品久久理论片 | 国产免费一区二区三区 | 成人久久久久久久久 | 男女羞羞视频免费观看 | 中文字幕在线观看亚洲 | 欧美 日韩 国产 一区 | 国产精品久久久久久久电影 | 国产欧美在线视频 | 亚洲欧美精品久久 | 欧日韩在线视频 | 亚洲精选一区 | 午夜成年人| 久久久久国产精品视频 | 国产精品久久久久无码av | 最近免费中文字幕在线视频2 | www.天天草| 青娱乐av | 欧美中文在线 | 日韩1区 | www.99久久久| 狠狠躁夜夜躁人人爽天天天天97 | h免费在线 | 精品96久久久久久中文字幕无 | 亚洲欧美日韩电影 | 国产欧美日韩综合精品一区二区 | 国产精品久久久久久久久免费丝袜 | 亚洲色域网 | 国产在线一区二区 | 九九综合久久 | 久久99精品久久久久国产越南 | 国产色在线 | 国产精品国产成人国产三级 | 成人aaa| 自拍偷拍在线视频 | 亚洲高清电影 | 骚视频在线观看 | 日韩欧美国产一区二区 | 81精品国产乱码久久久久久 | 国产精品久久一区二区三区 | 亚洲在线观看免费视频 | 久久精品欧美一区二区三区不卡 | 国产99久久久国产精品 | 国产日韩欧美精品一区二区三区 | 亚洲精品一区中文字幕乱码 | 国产精品亚洲精品日韩已方 | 国产精品久久久久久久久久免费看 | 欧美一区久久 | 99免费观看 | 免费成人在线观看视频 | 久久久亚洲精 | 久久福利| 夜本色| 亚洲成人另类 | 一区二区三区中文字幕 | 欧美精品亚洲精品 | 免费在线成人网 | japan护士性xxxⅹhd | 亚洲精品国产一区 | 在线免费黄色 | 欧美一级大片免费 | 久草毛片 | 欧美性猛交一区二区三区精品 | 免费黄色小视频 | 国产视频一区二区三区四区 | 一级黄色片在线 | 欧美 国产精品 | 久久福利 | 欧美日韩激情 | 亚洲一级黄色 | 成年人在线观看视频 | 少妇黄色一级片 | 国产成人一区二区三区 | h网站在线观看 | 嫩草视频网 | 亚洲免费一区 | 伊人无码高清 | 日本午夜精品 | 超碰在线人 | 精品国产成人 | 波多野结衣电影一区 | 久久久国产精品 | 亚洲成av人片在线观看 | 亚洲一区二区三 | 国产操片 | 亚洲毛片在线 | 欧美涩涩网 | 成人日批视频 | 国产91一区 | 国产成年人小视频 | 一本一道久久a久久精品逆3p | 美女一区 | 国产一区二区在线视频观看 | 国产精品亚洲一区二区三区在线 | 夜夜骑首页| 国产精品一区二 | 色噜噜狠狠狠综合曰曰曰88av | 99精品网站 | 欧美日韩午夜 | 久草视频在线播放 | 国产 欧美 日韩 一区 | 二区三区在线观看 | 亚洲福利精品 | 精品国产乱码久久久久久影片 | 亚洲久草 | 国产高清一二三区 | 91精品国产综合久久久久久丝袜 | 人人看超碰 | 国产精品久久久999 成人亚洲视频 | 色综合天天综合网国产成人网 | 国产精品久久久久久久久久久久久久 | 欧美亚洲二区 | 激情网站免费 | 久99视频| 九色在线| 国产精品免费观看 | 久久亚洲一区二区三区四区五区高 | 中文字幕乱码一区二区三区 | 欧美视频网站 | 日韩在线免费 | 久久av网| 亚洲人成在线播放 | av片网站 | 日韩精品久久久 | 亚洲精品在线视频 | 午夜精品久久久久久久久 | 噜噜噜噜狠狠狠7777视频 | 亚洲一区二区三区视频 | 日韩中文字幕免费在线 | 精品国产乱码久久久久久88av | 欧美专区在线 | 国产精品日韩在线观看 | 亚洲国产成人久久综合一区,久久久国产99 | 欧美日韩国产精品一区二区亚洲 | 色欧美日韩 | 久久99精品久久久久久久青青日本 | 在线国产一区 | 日本一级淫片免费看 | 91亚洲国产成人久久精品网站 | 久久久久久国产精品高清 | 在线一区视频 | 日本aⅴ毛片成人实战推荐 成人免毛片 | 亚洲精品亚洲人成人网 | 亚洲日本午夜 | 国产精品国产精品国产专区不片 | 精品国产一区二区三区性色av | 美女扒开内裤让男人桶 | 国产羞羞视频 | 国产不卡免费视频 | www.中文字幕| 久久99精品久久久 | 日韩在线播 | 中文二区 | 一区二区国产精品 | 精品久久99| 国产精品久久九九 | 国产精品久久久久久久久久大牛 | 国产视频第一页 | 拍拍无遮挡人做人爱视频免费观看 | 亚洲电影在线观看 | 一级大毛片| 色综合天天综合网国产成人网 | 成人精品国产一区二区4080 | 免费观看一区二区三区 | 日韩精品一区二区在线观看 | a级性生活片 | 国产精品视频入口 | 国产成人午夜精品影院游乐网 | 国产精品高潮呻吟久久av野狼 | 六月色婷婷 | 国产精品夜夜春夜夜爽久久电影 | 久久国产精品免费一区二区三区 | 久久久免费观看 | 精产国产伦理一二三区 | 女同理伦片在线观看禁男之园 | 欧美精品成人在线视频 | 久草青青| 成人av一区二区三区 | 欧美日韩高清 | www.福利视频 | 在线中文字幕日韩 | 国产91在线视频 | 精品久久久久久久人人人人传媒 | 欧美日韩国产在线播放 | 亚洲精品成人av | 欧美激情精品久久久久久 | 在线视频中文字幕 | 97精品国产97久久久久久粉红 | 欧美日韩成人在线视频 | 在线激情视频 | 国产精品乱码久久 | 亚洲精品视频在线播放 | 欧美视频一级 | 国产成人一区二区三区 | 日韩性在线 | 国产精品久久久久久久久免费桃花 | 欧美成人激情 | 国产午夜精品一区二区三区嫩草 | 成人网18免费网站 | 亚洲影视一区二区 | 国产精品视屏 | 中文字幕在线影院 | 成人一区二区在线 | 国产精品亚洲一区 | 99re在线 | 成人不卡视频 | 日本免费一区二区三区 | 欧美久久久久久 | 久久久www成人免费精品 | 精品亚洲一区二区三区四区五区 | 久久91精品国产 | 久久精品国产清自在天天线 | 91嫩草在线 | 日韩在线免费观看视频 | 日韩欧美在线播放 | 国内精品久久久久久中文字幕 | 日韩一区二区久久 | 精品毛片在线 | 日本久久久久 | 国产毛片视频 | 成人中文字幕在线 | 国产精品久久久久影院色老大 | 国产在线观看高清 | 国产精品丝袜视频 | 午夜你懂得 | 久久久亚洲精品中文字幕 | 亚洲国产精品va在线看黑人 | av免费网站在线观看 | 精品在线视频一区 | 九九r热| 天天爽夜夜爽 | 久久女同互慰一区二区三区 | 成人小视频在线观看 | 国产一区二区三区视频 | 国产一二三区在线观看 | 一区久久| 久久久精品免费观看 | 欧美综合久久久 | 亚洲高清久久 | 中文字幕一二区 | 我爱操 | 欧美日韩久久久久 | 北条麻妃国产九九九精品小说 | 99国产精品久久 | 久久免费视频国产 | 国产精品久久久久久福利一牛影视 | 久久欧美视频 | 日日爱夜夜爱 | 毛片免费看| 成人在线观看免费 | 久久久久中文字幕 | 成人看片免费 | 国产97碰免费视频 | 国产精品久久久 | 精品欧美一区二区三区久久久小说 | 日韩一区二区免费视频 | 懂色一区二区三区免费观看 | 成人在线播放 | 精品免费国产 | 日韩精品在线观看视频 | 日本一区视频在线观看 | 久久精品不卡 | 久久福利 | 全毛片 | 韩日精品一区 | 精品久久一级片 | 亚洲国产成人av | 国产一区二区视频免费看 | 日本精品免费 | 精品一区二区在线观看 | 国产三区四区 | 91福利网站在线观看 | 日本高清视频网站www | 91久色| 免费大片黄在线观看 | 国产黄色一级大片 | 91亚洲国产成人久久精品网站 | 日本精品一区二区在线观看 | 国产成人午夜 |