Django入门教程(二)
? ? ? 建議直接閱讀末尾!!!
Writing your first Django app, part 2
?本節將設置數據庫,創建您的第一個模型(model),并簡單介紹Django自動生成的管理頁面。
數據庫設置
現在,打開mysite/settings.py。這是一個普通的Python模塊,代表Django配置的模塊級變量。
默認情況下,配置使用SQLite。如果你初涉數據庫,或者只想嘗試Django,這是最簡單的選擇。SQLlite包含在Python中,所以你不需要安裝對數據庫的支持。當您開始第一個真正的項目時,您可能希望使用想 PostgreSQL這樣更具擴展性的數據庫,以避免數據庫切換造成的頭痛。
如果您想使用其他數據庫,需要安裝響應的數據庫綁定,并配置以下DATABASES 'default'中的項目來匹配您的數據庫連接:
- ENGINE -- 可以為'django.db.backends.sqlite3', 'django.db.backends.postgresql', 'django.db.backends.mysql'或者'django.db.backends.oracle'。其他后端也允許使用。
- NAME -- 數據庫的名稱。如果使用SQLite,數據庫就是電腦中的一個文件,那么NAME應該是該文件的完整絕對路徑(包括文件名)。默認值os.path.join(BASE_DIR, 'db.sqlite3'),會將數據庫文件保存在您的項目目錄中。
如果不是用SQLite作為數據庫,需要添加USER,PASSWORD和HOST等附加值。詳細操作請參考DATABASES。
還需要注意在該文件頂部的INSTALLED_APPS配置。它包含了在該Django實例中激活的所有Django應用的名稱。Apps(應用)可以被多個項目使用,你可以打包并發布給其他項目。
默認情況下,INSTALLED_APPS包含以下應用,這些應用隨Django一起提供:
- django.contrib.admin -- 管理站點。你會很快用到它。
- django.contrib.auth -- 認證系統。
- django.contrib.contenttypes -- 內容類型的框架。
- django.contrib.sessions -- 會話框架。
- django.contrib.messages -- 消息框架。
- django.contrib.staticfiles -- 管理靜態文件的框架。
這些應用一般情況下被默認包含在內。
其中一些應用要使用至少一張數據表,所以我們在使用它們之前需要創建一張數據表。為此,運行一下命令:
$ python manage.py migrate?
migrate命令會查看INSTALLED_APPS配置,并根據mysite/setting.py文件中的數據庫配置和應用程序隨附的數據遷移來創建所有必需的數據庫(稍后介紹)。你將看到每個數據遷移的信息。如果你有興趣,您可以在數據庫的命令行客戶端輸入\dt(PostgreSQL), SHOW TABLES;(MySQL), .schema(SQLite) 或者 SELECT TABLE_NAME FROM USER_TABLES;(Oracle)來顯示Django創建的數據表。
?
創建模型(model)
現在我們通過使用額外的元數據來來定義自己的模型(本質上就是數據庫的布局)。
?
在我們的poll應用中,我們將創建兩個模型:Question和Choice。每個Question有一個問題和一個發布日期。每個Choice有兩個字段:選擇文本和投票計數器。每個Choice都和一個Question相關聯。
這些概念由簡單Python類表示,編輯polls/models.py文件:
1 # polls/models.py 2 3 from django.db import models 4 5 6 class Question(models.Model): 7 question_text = models.CharField(max_length=200) 8 pub_date = models.DateTimeField('date published') 9 10 11 class Choice(models.Model): 12 question = models.ForeignKey(Question, on_delete=models.CASCADE) 13 choice_text = models.CharField(max_length=200) 14 votes = models.IntegerField(default=0)?
代碼很簡單。每個模型都由一個繼承自django.db.models.Model的子類表示。每個模型中都有一些類的變量,每個模型中的變量代表一個數據庫字段。
每個字段由由Field類的實例表示,例如,CharField用于字符字段,DateTimeField用于時期。這告訴Django每個字段代表什么類型的數據。
每個Field實例的名稱(例如question_text, pub_date)就是字段的名稱(以機器友好的格式書寫)。你將在Python代碼中使用這些值,你的數據庫將使用它作為列名稱。
你可以使用可選的第一個位置參數來給Field指定一個方便人理解(human-readable)的名稱。這用于Django的幾個內省的部分,它可以作為文檔。如果該字段沒有提供,Django將使用機器刻度(machine-readable)的名稱。在本例中,我們只為Question.pub_date字段定義了人類的可讀(human-readable)的名稱。本例中的其他字段,字段的機器名稱足夠作為人類可讀的名稱。(翻譯完這段感覺自己已經成仙了/(ㄒoㄒ)/~~)
一些Field類有必要的參數。例如CharField,要求給它一個max_length。這不僅在數據庫架構中使用,而且用于驗證,我們即將看到。
Field也可能存在一些可選參數,本例中,我們為votes設置了default值為0。
最后,注意一個關聯的定義,使用ForeignKey。它告訴Django每個Choice都與一個Question關聯。Django支持所有常見的數據庫關聯:多對一,多對多,一對一。
?
激活模型
那個小的模型代碼給了Django很多信息。有個它,Django可以:
- 為這個應用(app)創建數據庫(CREATE TABLE語句);
- 創建用于訪問Question和Choice的數據庫訪問API。
但是,首先我們需要告訴我們的項目,polls應用已安裝。
(提示:Django的應用是“可插拔”的:你可以將一個app使用在多個項目中,也可以發布你的apps,因為它們并不予給定的Django安裝綁定!)
來將應用包含到我們的項目中,我們需要在INSTALLED_APPS配置中添加對其配置類的引用。本例的配置類即polls/apps.py文件中的PollsConfig類,所以它的引用路徑為"polls.apps.PollsConfig"。編輯mysite/settings.py文件,添加該路徑到INSTALLED_APPS配置中。
1 # mysite/settings.py 2 3 INSTALLED_APPS = [ 4 'django.contrib.admin', 5 'django.contrib.auth', 6 'django.contrib.contenttypes', 7 'django.contrib.sessions', 8 'django.contrib.messages', 9 'django.contrib.staticfiles', 10 'polls.apps.PollsConfig', 11 ]?
(簡單寫法,可以直接添加應用名即"polls",因為配置類PollsConfig中定義了"name='polls'")
現在Django知道已包含了polls應用。讓我們運行另一個命令:
$ python manage.py makemigrations polls?
你可以看到類似下面的內容:
Migrations for 'polls':polls/migrations/0001_initial.py:- Create model Choice- Create model Question- Add field question to choice?
通過運行makemigrations,你告訴Django,你已經對模型進行了一些修改(在這種情況下,你已經創建了新的模型),并希望將這些修改存儲為一個遷移(migration)。
Migration(遷移)是“Django如何修改你的模型(以及數據庫結構)” --它們只是磁盤上的文件。如果你喜歡,可以閱讀新模型的遷移,即文件polls/migrations/0001_initial.py。不要擔心,Django創建該文件時你不需要去一一閱讀,但是它們被設計成可編輯的,你可以手動調整Django修改數據的行為。
有一個命令會運行你的migration并自動管理你的數據庫結構 -- 調用migrate命令,稍后介紹該命令。首先,讓我們來看看migration會運行哪些SQL語句。sqlmagrate命令接受應用名和migration名稱,并返回SQL語句:
$ python manage.py sqlmigrate polls 0001您應該看到類似于以下內容(我們已經將內容重新格式化的更為易讀):
BEGIN; -- -- Create model Choice -- CREATE TABLE "polls_choice" ("id" serial NOT NULL PRIMARY KEY,"choice_text" varchar(200) NOT NULL,"votes" integer NOT NULL ); -- -- Create model Question -- CREATE TABLE "polls_question" ("id" serial NOT NULL PRIMARY KEY,"question_text" varchar(200) NOT NULL,"pub_date" timestamp with time zone NOT NULL ); -- -- Add field question to choice -- ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL; ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT; CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id"); ALTER TABLE "polls_choice"ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"FOREIGN KEY ("question_id")REFERENCES "polls_question" ("id")DEFERRABLE INITIALLY DEFERRED;COMMIT;?
請注意以下事項:
- 確切的輸出內容將取決于你使用的數據庫。上面例子由PostgreSQL生成。(這個文檔有坑啊,不是說好的用SQLite嗎)。
- 表名是結合應用名稱和小寫的model名稱(question和choice)自動生成的。(你可以重寫這個行為)
- 主鍵(ID)將自動添加。如果你在編寫model的時候已經添加了主鍵,就不會自動生成主鍵ID了。(這個也可以重寫)
- 按照管理,Django會追加"_id"給外鍵字段名。(你猜我要說什么?是的,這個還是可以重寫)
- 外鍵關聯由FOREIGN KEY顯式聲明。不要擔心DEFERRABLE部分;它只是為了告訴PostgreSQL不要在事務結束前執行外鍵。
- 它會適應你使用的數據庫,所以數據庫的一些特殊字段類型(例如auto_increment--MySQL, serial -- PostgreSQL, integer primary key autoincrement -- SQLite)會自動為你處理。同樣適用于對字段名的引用,例如使用雙引號或者單引號。
- sqlmigrate命令實際上不會在數據庫上運行migration命令,它只是將Django認為需要執行的SQL語句打印到屏幕上,以便你能看到。這對于檢查Django將要執行的操作非常有用?or if you have database administrators who require SQL scripts for changes.(這一句不太懂,先上原文)
如果你有興趣,可以執行python manage.py check;它會檢查項目中的所有問題,而不會執行遷移(migration)或創建數據庫。
現在,再次執行migrate,在你的數據庫中創建這些模型(model)的表:
$ python manage.py migrate Operations to perform:Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations:Rendering model states... DONEApplying polls.0001_initial... OK?
migrate命令使用所有未執行的migration(Django會調用django_migrations跟蹤哪個申請使用數據庫中的特殊表)并根據數據庫運行它們 -- 本質上,將你對模型(model)做的修改同步到數據庫的結構中。
Migration非常強大,在開發項目的過程中,使你可以隨著時間的推移來修改模型,而不需要刪除數據庫或表再創建一個新的 -- 它專門用來實時更新數據庫,而不會丟失數據。我們將在本教程的后續部分中更深入地介紹它們,但是現在,請記住進行模型更改的三步指南:
- 修改你的模型(在models.py文件中)
- 執行python manage.py makemigrations 為這些修改創建遷移
- 執行 python manage.py migerate 將這些修改應用到數據庫中。
將創建和應用migration分為兩個命令的原因是你將提交migration到版本控制系統并發送到你的應用;它們不僅可以使您的開發更容易,而且還可以被其他開發人員和在生產中使用。
閱讀django-admin documentation了解有關manage.py實用程序可執行操作得當詳細信息。
?
使用API
現在,讓我們進入交互式的python shell,并使用Django提供的免費API。要調用Python shell,請使用以下命令:
$ python manage.py shell我們使用這個,而不是簡單的輸入"python",因為manage.py設置了DJANGO_SETTING_MODULE環境變量,它告訴Django mysite/settings.py文件的python導入路徑。
一旦你進入shell,請探索database API:
>>> from polls.models import Question, Choice # 導入我們剛寫的模型# 系統中還沒有“問題” >>> Question.objects.all() <QuerySet []># 創建一個新“問題” # 配置文件中默認啟動對時區的支持, 所以Django需要提供一個tzinfo的日期給pub_date.使用timezone.now() # 而不是datetime.datetime.now() >>> from django.utils import timezone >>> q = Question(question_text="What's new?", pub_date=timezone.now())# 將對象保存到數據庫中。你必須顯式調用save()>>> q.save()# 現在它有一個ID,注意,你可能說是‘1L’而不是‘1’,這取決于你使用的數據庫。這意味著你的數據庫后端更喜歡返回
# 整數作為Python的長整型對象。 >>> q.id 1# 通過Python屬性訪問模型字段值.
>>> q.question_text "What's new?" >>> q.pub_date datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)# 通過更改屬性來更改值,然后調用save().
>>> q.question_text = "What's up?" >>> q.save()# oobjects.all()顯示數據庫中的所有問題.
>>> Question.objects.all() <QuerySet [<Question: Question object>]>
?
等一下,<Question: Question object>是對該對象完全無毛用的表示。讓我們通過編輯Question模型(在polls/models.py文件中),并在Question和Choice中添加__str__()方法:
1 # polls/models.py 2 3 from django.db import models 4 from django.utils.encoding import python_2_unicode_compatible 5 6 @python_2_unicode_compatible # only if you need to support Python 2 7 class Question(models.Model): 8 # ... 9 def __str__(self): 10 return self.question_text 11 12 @python_2_unicode_compatible # only if you need to support Python 2 13 class Choice(models.Model): 14 # ... 15 def __str__(self): 16 return self.choice_text?
__str__()方法對模型非常重要,這不僅在處理交互式提示時方便您使用,還因為Django自動生成的admin中使用了對象的表示。
注意這些是普通的Python方法。我們添加一個自定義的方法,只是為了演示:
?
# polls/models.pyimport datetimefrom django.db import models from django.utils import timezoneclass Question(models.Model):# ...def was_published_recently(self):return self.pub_date >= timezone.now() - datetime.timedelta(days=1)注意 import datettime 和 from django.utils import timezone,它們分別參考Python標準庫的datetime模塊和Django中django.utils.timezone的時區關聯工具。如果您不熟悉Python中的時區處理,您可以在時區支持文檔中了解更多信息。
保存這些更改并重新啟動一個新的Python交互式shell?:python manage.py shell
>>> from polls.models import Question, Choice# Make sure our __str__() addition worked. >>> Question.objects.all() <QuerySet [<Question: What's up?>]># Django provides a rich database lookup API that's entirely driven by # keyword arguments. >>> Question.objects.filter(id=1) <QuerySet [<Question: What's up?>]> >>> Question.objects.filter(question_text__startswith='What') <QuerySet [<Question: What's up?>]># Get the question that was published this year. >>> from django.utils import timezone >>> current_year = timezone.now().year >>> Question.objects.get(pub_date__year=current_year) <Question: What's up?># Request an ID that doesn't exist, this will raise an exception. >>> Question.objects.get(id=2) Traceback (most recent call last):... DoesNotExist: Question matching query does not exist.# Lookup by a primary key is the most common case, so Django provides a # shortcut for primary-key exact lookups. # The following is identical to Question.objects.get(id=1). >>> Question.objects.get(pk=1) <Question: What's up?># Make sure our custom method worked. >>> q = Question.objects.get(pk=1) >>> q.was_published_recently() True# Give the Question a couple of Choices. The create call constructs a new # Choice object, does the INSERT statement, adds the choice to the set # of available choices and returns the new Choice object. Django creates # a set to hold the "other side" of a ForeignKey relation # (e.g. a question's choice) which can be accessed via the API. >>> q = Question.objects.get(pk=1)# Display any choices from the related object set -- none so far. >>> q.choice_set.all() <QuerySet []># Create three choices. >>> q.choice_set.create(choice_text='Not much', votes=0) <Choice: Not much> >>> q.choice_set.create(choice_text='The sky', votes=0) <Choice: The sky> >>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)# Choice objects have API access to their related Question objects. >>> c.question <Question: What's up?># And vice versa: Question objects get access to Choice objects. >>> q.choice_set.all() <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]> >>> q.choice_set.count() 3# The API automatically follows relationships as far as you need. # Use double underscores to separate relationships. # This works as many levels deep as you want; there's no limit. # Find all Choices for any question whose pub_date is in this year # (reusing the 'current_year' variable we created above). >>> Choice.objects.filter(question__pub_date__year=current_year) <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]># Let's delete one of the choices. Use delete() for that. >>> c = q.choice_set.filter(choice_text__startswith='Just hacking') >>> c.delete()有關模型關系的更多信息,請參閱訪問相關對象。有關如何使用雙下劃線通過API執行字段查找的更多信息,請參閱字段查找。有關數據庫API的完整詳細信息,請參閱我們的數據庫API參考。
?
?
本人寫這篇翻譯是英語實在吃力,閱讀原文檔的時候很費勁,回看下內容更麻煩,所以想著一邊看以便翻譯出來,最后發現。。效率好低呀,這點東西竟然寫了十幾個小時,對本人英語水平默哀三分鐘。。。
所以我只寫了這么斷章的一篇,不過我發現了一個不錯的博客,這位大神已經把入門的部分都翻譯出來了,所以我就沒有然后了
大神鏈接:“全能”選手—Django 1.10文檔中文版
?
轉載于:https://www.cnblogs.com/thunderLL/p/6637139.html
總結
以上是生活随笔為你收集整理的Django入门教程(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于mysql主从同步的proxy读写分
- 下一篇: 用html+ccs3就能 做出一个太阳系