在Django框架中運行Python應用全攻略
我們來假定下面的這些概念、字段和關(guān)系:
- 一個作者有姓,有名及email地址。
- 出版商有名稱,地址,所在城市、省,國家,網(wǎng)站。
- 書籍有書名和出版日期。 它有一個或多個作者(和作者是多對多的關(guān)聯(lián)關(guān)系[many-to-many]), 只有一個出版商(和出版商是一對多的關(guān)聯(lián)關(guān)系[one-to-many],也被稱作外鍵[foreign key])
第一步是用Python代碼來描述它們。 打開由`` startapp`` 命令創(chuàng)建的models.py 并輸入下面的內(nèi)容:
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
讓我們來快速講解一下這些代碼的含義。 首先要注意的事是每個數(shù)據(jù)模型都是 django.db.models.Model 的子類。它的父類 Model 包含了所有必要的和數(shù)據(jù)庫交互的方法,并提供了一個簡潔漂亮的定義數(shù)據(jù)庫字段的語法。 信不信由你,這些就是我們需要編寫的通過Django存取基本數(shù)據(jù)的所有代碼。
每個模型相當于單個數(shù)據(jù)庫表,每個屬性也是這個表中的一個字段。 屬性名就是字段名,它的類型(例如 CharField )相當于數(shù)據(jù)庫的字段類型 (例如 varchar )。例如, 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 可以自動生成這些 CREATE TABLE 語句。
“每個數(shù)據(jù)庫表對應一個類”這條規(guī)則的例外情況是多對多關(guān)系。 在我們的范例模型中, Book 有一個 多對多字段 叫做 authors 。 該字段表明一本書籍有一個或多個作者,但 Book 數(shù)據(jù)庫表卻并沒有 authors 字段。 相反,Django創(chuàng)建了一個額外的表(多對多連接表)來處理書籍和作者之間的映射關(guān)系。
請查看附錄 B 了解所有的字段類型和模型語法選項。
最后需要注意的是,我們并沒有顯式地為這些模型定義任何主鍵。 除非你單獨指明,否則Django會自動為每個模型生成一個自增長的整數(shù)主鍵字段每個Django模型都要求有單獨的主鍵。
模型安裝
完成這些代碼之后,現(xiàn)在讓我們來在數(shù)據(jù)庫中創(chuàng)建這些表。 要完成該項工作,第一步是在 Django 項目中 激活 這些模型。 將 books app 添加到配置文件的已安裝應用列表中即可完成此步驟。
再次編輯 settings.py 文件, 找到 INSTALLED_APPS 設(shè)置。 INSTALLED_APPS 告訴 Django 項目哪些 app 處于激活狀態(tài)。 缺省情況下如下所示:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', )
把這四個設(shè)置前面加#臨時注釋起來。 (這四個app是經(jīng)常使用到的,我們將在后續(xù)章節(jié)里討論如何使用它們)。同時,注釋掉MIDDLEWARE_CLASSES的默認設(shè)置條目,因為這些條目是依賴于剛才我們剛在INSTALLED_APPS注釋掉的apps。 然后,添加`` ‘mysite.books'`` 到`` INSTALLED_APPS`` 的末尾,此時設(shè)置的內(nèi)容看起來應該是這樣的:
MIDDLEWARE_CLASSES = ( # 'django.middleware.common.CommonMiddleware', # 'django.contrib.sessions.middleware.SessionMiddleware', # 'django.contrib.auth.middleware.AuthenticationMiddleware', ) INSTALLED_APPS = ( # 'django.contrib.auth', # 'django.contrib.contenttypes', # 'django.contrib.sessions', # 'django.contrib.sites', 'mysite.books', )
(就像我們在上一章設(shè)置TEMPLATE_DIRS所提到的逗號,同樣在INSTALLED_APPS的末尾也需添加一個逗號,因為這是個單元素的元組。 另外,本書的作者喜歡在 每一個 tuple元素后面加一個逗號,不管它是不是 只有一個元素。 這是為了避免忘了加逗號,而且也沒什么壞處。)
'mysite.books'指示我們正在編寫的books app。 INSTALLED_APPS 中的每個app都使用 Python的路徑描述,包的路徑,用小數(shù)點“.”間隔。
現(xiàn)在我們可以創(chuàng)建數(shù)據(jù)庫表了。 首先,用下面的命令驗證模型的有效性:
python manage.py validate
validate 命令檢查你的模型的語法和邏輯是否正確。 如果一切正常,你會看到 0 errors found 消息。如果出錯,請檢查你輸入的模型代碼。 錯誤輸出會給出非常有用的錯誤信息來幫助你修正你的模型。
一旦你覺得你的模型可能有問題,運行 python manage.py validate 。 它可以幫助你捕獲一些常見的模型定義錯誤。
模型確認沒問題了,運行下面的命令來生成 CREATE TABLE 語句(如果你使用的是Unix,那么可以啟用語法高亮):
python manage.py sqlall books
在這個命令行中, books 是app的名稱。 和你運行 manage.py startapp 中的一樣。執(zhí)行之后,輸出如下:
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_author" ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(40) NOT NULL, "email" varchar(75) 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") DEFERRABLE INITIALLY DEFERRED, "publication_date" date NOT NULL ) ; CREATE TABLE "books_book_authors" ( "id" serial NOT NULL PRIMARY KEY, "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED, "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED, UNIQUE ("book_id", "author_id") ) ; CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id"); COMMIT;
注意:
- 自動生成的表名是app名稱( books )和模型的小寫名稱 ( publisher , book , author )的組合。你可以參考附錄B重寫這個規(guī)則。
- 我們前面已經(jīng)提到,Django為每個表格自動添加加了一個 id 主鍵, 你可以重新設(shè)置它。
- 按約定,Django添加 "_id" 后綴到外鍵字段名。 你猜對了,這個同樣是可以自定義的。
- 外鍵是用 REFERENCES 語句明確定義的。
- 這些 CREATE TABLE 語句會根據(jù)你的數(shù)據(jù)庫而作調(diào)整,這樣象數(shù)據(jù)庫特定的一些字段例如:(MySQL),auto_increment(PostgreSQL),serial(SQLite),都會自動生成。integer primary key 同樣的,字段名稱也是自動處理(例如單引號還好是雙引號)。 例子中的輸出是基于PostgreSQL語法的。
sqlall 命令并沒有在數(shù)據(jù)庫中真正創(chuàng)建數(shù)據(jù)表,只是把SQL語句段打印出來,這樣你可以看到Django究竟會做些什么。 如果你想這么做的話,你可以把那些SQL語句復制到你的數(shù)據(jù)庫客戶端執(zhí)行,或者通過Unix管道直接進行操作(例如,`` python manager.py sqlall books | psql mydb`` )。不過,Django提供了一種更為簡易的提交SQL語句至數(shù)據(jù)庫的方法: `` syncdb`` 命令
python manage.py syncdb
執(zhí)行這個命令后,將看到類似以下的內(nèi)容:
Creating table books_publisher Creating table books_author Creating table books_book Installing index for books.Book model
syncdb 命令是同步你的模型到數(shù)據(jù)庫的一個簡單方法。 它會根據(jù) INSTALLED_APPS 里設(shè)置的app來檢查數(shù)據(jù)庫, 如果表不存在,它就會創(chuàng)建它。 需要注意的是, syncdb 并 不能將模型的修改或刪除同步到數(shù)據(jù)庫;如果你修改或刪除了一個模型,并想把它提交到數(shù)據(jù)庫,syncdb并不會做出任何處理。 (更多內(nèi)容請查看本章最后的“修改數(shù)據(jù)庫的架構(gòu)”一段。)
如果你再次運行 python manage.py syncdb ,什么也沒發(fā)生,因為你沒有添加新的模型或者 添加新的app。因此,運行python manage.py syncdb總是安全的,因為它不會重復執(zhí)行SQL語句。
如果你有興趣,花點時間用你的SQL客戶端登錄進數(shù)據(jù)庫服務器看看剛才Django創(chuàng)建的數(shù)據(jù)表。 你可以手動啟動命令行客戶端(例如,執(zhí)行PostgreSQL的`` psql`` 命令),也可以執(zhí)行 `` python manage.py dbshell`` ,這個命令將依據(jù)`` DATABASE_SERVER`` 的里設(shè)置自動檢測使用哪種命令行客戶端。 常言說,后來者居上。
基本數(shù)據(jù)訪問
一旦你創(chuàng)建了模型,Django自動為這些模型提供了高級的Python API。 運行 python manage.py shell 并輸入下面的內(nèi)容試試看:
>>> from books.models import Publisher >>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue', ... city='Berkeley', state_province='CA', country='U.S.A.', ... website='http://www.apress.com/') >>> p1.save() >>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.', ... city='Cambridge', state_province='MA', country='U.S.A.', ... website='http://www.oreilly.com/') >>> p2.save() >>> publisher_list = Publisher.objects.all() >>> publisher_list [<Publisher: Publisher object>, <Publisher: Publisher object>]
這短短幾行代碼干了不少的事。 這里簡單的說一下:
- 首先,導入Publisher模型類, 通過這個類我們可以與包含 出版社 的數(shù)據(jù)表進行交互。
- 接著,創(chuàng)建一個`` Publisher`` 類的實例并設(shè)置了字段`` name, address`` 等的值。
- 調(diào)用該對象的 save() 方法,將對象保存到數(shù)據(jù)庫中。 Django 會在后臺執(zhí)行一條 INSERT 語句。
- 最后,使用`` Publisher.objects`` 屬性從數(shù)據(jù)庫取出出版商的信息,這個屬性可以認為是包含出版商的記錄集。 這個屬性有許多方法, 這里先介紹調(diào)用`` Publisher.objects.all()`` 方法獲取數(shù)據(jù)庫中`` Publisher`` 類的所有對象。這個操作的幕后,Django執(zhí)行了一條SQL `` SELECT`` 語句。
這里有一個值得注意的地方,在這個例子可能并未清晰地展示。 當你使用Django modle API創(chuàng)建對象時Django并未將對象保存至數(shù)據(jù)庫內(nèi),除非你調(diào)用`` save()`` 方法:
p1 = Publisher(...) # At this point, p1 is not saved to the database yet! p1.save() # Now it is.
如果需要一步完成對象的創(chuàng)建與存儲至數(shù)據(jù)庫,就使用`` objects.create()`` 方法。 下面的例子與之前的例子等價:
>>> p1 = Publisher.objects.create(name='Apress', ... address='2855 Telegraph Avenue', ... city='Berkeley', state_province='CA', country='U.S.A.', ... website='http://www.apress.com/') >>> p2 = Publisher.objects.create(name="O'Reilly", ... address='10 Fawcett St.', city='Cambridge', ... state_province='MA', country='U.S.A.', ... website='http://www.oreilly.com/') >>> publisher_list = Publisher.objects.all() >>> publisher_list
當然,你肯定想執(zhí)行更多的Django數(shù)據(jù)庫API試試看,不過,還是讓我們先解決一點煩人的小問題。
添加模塊的字符串表現(xiàn)
當我們打印整個publisher列表時,我們沒有得到想要的有用信息,無法把````對象區(qū)分開來:
System Message: WARNING/2 (<string>, line 872); backlink Inline literal start-string without end-string. System Message: WARNING/2 (<string>, line 872); backlink Inline literal start-string without end-string. [<Publisher: Publisher object>, <Publisher: Publisher object>]
我們可以簡單解決這個問題,只需要為Publisher 對象添加一個方法 __unicode__() 。 __unicode__() 方法告訴Python如何將對象以unicode的方式顯示出來。 為以上三個模型添加__unicode__()方法后,就可以看到效果了:
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() **def __unicode__(self):** **return self.name** class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() **def __unicode__(self):** **return u'%s %s' % (self.first_name, self.last_name)** class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() **def __unicode__(self):** **return self.title**
就象你看到的一樣, __unicode__() 方法可以進行任何處理來返回對一個對象的字符串表示。 Publisher和Book對象的__unicode__()方法簡單地返回各自的名稱和標題,Author對象的__unicode__()方法則稍微復雜一些,它將first_name和last_name字段值以空格連接后再返回。
對__unicode__()的唯一要求就是它要返回一個unicode對象 如果`` __unicode__()`` 方法未返回一個Unicode對象,而返回比如說一個整型數(shù)字,那么Python將拋出一個`` TypeError`` 錯誤,并提示:”coercing to Unicode: need string or buffer, int found” 。
相關(guān)文章
Python中創(chuàng)建字典的幾種方法總結(jié)(推薦)
下面小編就為大家?guī)硪黄狿ython中創(chuàng)建字典的幾種方法總結(jié)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-0410種檢測Python程序運行時間、CPU和內(nèi)存占用的方法
這篇文章主要介紹了10種檢測Python程序運行時間、CPU和內(nèi)存占用的方法,包括利用Python裝飾器或是外部的Unix Shell命令等,需要的朋友可以參考下2015-04-04Python 使用SMTP發(fā)送郵件的代碼小結(jié)
python的smtplib提供了一種很方便的途徑發(fā)送電子郵件。它對smtp協(xié)議進行了簡單的封裝,需要的朋友可以參考下2016-09-09用python wxpy管理微信公眾號并利用微信獲取自己的開源數(shù)據(jù)
這篇文章主要介紹了用python wxpy管理微信公眾號并利用微信獲取自己的開源數(shù)據(jù),本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07解決pytorch多GPU訓練保存的模型,在單GPU環(huán)境下加載出錯問題
這篇文章主要介紹了解決pytorch多GPU訓練保存的模型,在單GPU環(huán)境下加載出錯問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06Python?NLP開發(fā)之實現(xiàn)聊天機器人
這篇文章主要為大家介紹了Python如何實現(xiàn)聊天機器人,即使用自然語言處理?(NLP)?來幫助用戶通過文本、圖形或語音與?Web?服務或應用進行交互,感興趣的可以了解一下2023-05-05