【譯】本身動手寫Django app,第一部分【完】

原文地址:https://docs.djangoproject.com/en/1.4/intro/tutorial01/ php

讓咱們經過例子來學習。 python

經過這個教程,咱們將帶領你瞭解建立基本的調查程序。 mysql

它將包括兩部分: linux

一個讓人們能夠查看調查和投票的網址; sql

一個可讓你增長,改變和刪除調查的管理員網址。 shell

假設你已經安裝了Django。你能夠在python交互式解釋器中輸入 import django,若是成功,沒有錯誤的話,就說明Django已經安裝。 數據庫

1、建立一個項目 django

若是這是你第一次用Django,你必須注意一些初始的設置。也就是說,你須要自動生成一些代碼來創建一個Django項目--Django實例設置的集合,包括數據庫的配置,Django相關的選項和應用程序相關的設置。 windows

從命令行上cd到你想儲存你代碼的目錄,而後輸入django-admin.py startproject mysite,這將建立在當前目錄建立一個mysite目錄。 安全

(不一樣發行版本可能有不一樣的腳本名稱:若是你用linux發行版的包管理器(apt-get或者yun)安裝Django,django-admin.py可能被重命名爲django-admin,你能夠在接下來的命令行都忽視.py繼續這個文檔。)

(Mac OS許可:若是你使用Mac OS X,當你嘗試運行django-admin.py startproject時你可能看到」permission denied「的消息。這是由於在基於Unix的系統像OS X,只有一個文件被標記爲」executable「才能運行這個程序。爲了這樣作,打開Terminal.app,而後進入django-admin.py安裝的那個目錄,運行 chmod +x django-admin.py。)

(注意:你須要避免用python內建關鍵詞或者是Django組件來命名你的項目。特別地就是說你應該避免用像django或者test這些名字。)

當你經過python setup.py安裝Django以後django-admin.py應該在你係統路徑裏(我猜是環境變量),若是不在你的系統路徑裏,你能夠在site-packages/django/django/bin下找到它(site-packages是你python安裝目錄下的一個目錄),而後把django-admin.py連接到你的路徑下,不如說/usr/local/bin。

(這些代碼該存在什麼地方:若是你用的是php,你可能習慣於把你的代碼放在服務器的根文檔下(在一個地方好比說/var/www)。可是用Django,你不須要這樣,由於這別人就有可能經過網絡看到你代碼風險,這是不安全的。

把你的代碼放在你跟物件目錄以外,好比說/home/mycode.)

讓咱們來看一下startproject建立了什麼:

mysite:

    manage.py

    mysite/

        __init__.py

        settings.py

        urls.py

        wsgi.py

(和你看到的不匹配?項目默認的佈局最近改變了,若是你看到的是一個「平坦的」佈局(也就是說沒有mysite/目錄),你可能用一個不符合這個教程版本的Django,你能夠切換到老版本的教程或者使用新版本的Django。)

這些文件是:

外面的mysite/目錄只是一個你項目的容器,它的名字和Django無關,你能夠把它重命名成任何你喜歡的名字;

manage.py:一個讓你和Django項目多途徑交互的命令行實用程序,你能夠在django-admin.py 和manage.py中瞭解更過關於manage.py的細節;

內部的mysite/目錄是你項目的實際python包,它的名字是python包的名字,你能夠經過導入(import mysite.settings)來使用它裏面的一切;

mysite/__init__.py:一個空文件,用來告訴python這個目錄應該被當成一個python包處理。(若是你是個新手,你能夠在官方文檔中瞭解到更更多關於包的信息。)

mysite/settings.py:Django項目的設置和配置。Django設置會告訴你設置時如何工做的;

mysite/urls.py:Django項目的URL聲明,你Django支持的網址的目錄,你可在URL分配中瞭解到個呢更多關於URLs的信息;

mysite/wsgi.py:兼容WSGI的網絡服務器運行你項目的進入點,你何以在如何部署WSGI中瞭解到更多細節;

2、開發服務器

讓咱們來驗證它已經工做了。改變目錄到外面的mysite目錄下,運行命令:python manage.py runserver,你能夠在命令行上看到以下輸出信息:

Validating models...
0 errors found.

Django version 1.4, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
你已經開啓了Django開發服務器,這是一個徹底用python寫的輕量級的網絡服務器,咱們已經在Django中包含了這個,所以你能夠快速的開發而不用擔憂如何處理配置一個上線服務器--好比說Apache--直到你準備上線了。

如今要標註一下:不要在任何相似的上線(生產)環境中使用這個服務器。這只是在開發是使用的。(咱們如今是在建立網絡架構,不是網絡服務器。)
如今既然服務器已經運行起來了,你能夠經過服務器訪問http://127.0.0.1:8000/,你將會看到一個愉快的,淡藍色蠟筆寫的「Welcome to Django」的網頁,你成功了!

(改變端口:默認狀況下,runserver命令在內部IP端口8000啓動開發服務器,若是你想改變服務器的端口,在命令行的參數中聲明。好比說,下面的命令在8080端口啓動服務器: python manage.py runserver 8080;若是你想改變服務器的IP,把它和端口一塊兒在命令行中聲明,所以爲了監聽全部公共IP(當你想在其餘電腦上展現你的工做的時候頗有用),用:python manage.py runserver 0.0.0.0:8000,你能夠在runserver參考手冊中找到更多關於開發服務器的文檔。)

3、創建數據庫

如今,編輯mysite/settings.py,這是一個表明Django設置的帶有模塊層變量的常規python模塊,改變DATABASE‘default’關鍵詞使之和你的數據庫鏈接設置相匹配。

ENGINE:要麼是‘django.db.backends.postgresql_psycopg2',要麼是’django.db.backends.mysql',要麼是'django.db.backends.sqlites3',或者是'django.db.backends.oracle',其餘的選項詳見文檔;

NAME:數據庫的名字。若是你用的是SQLite,數據庫多是你電腦上的一個文件,這種狀況下,NAME應該是絕對值路徑,包括數據庫文件名,若是文件不存在,當你第一次同步數據庫的時候系統將會自動建立該文件。在明確路徑是,老是使用正斜槓,甚至是在windows上(好比說,C:/homes/user/mysite/sqlite3.db);

USER:數據庫的用戶名(SQLite設置爲空);

PASSWORD:數據庫密碼(SQLite設置爲空);

HOST:存放數據庫的主機,若是數據庫服務器是在同一個物理機器上面,這是該選項爲空字符串;

若是你是數據庫方面的新手,咱們建議使用SQLite,這是設置ENGINE爲‘django.db.backends.sqlite3’而且把NAME設置成存放你數據庫的地方就好了。在python2.5和之後的版本中,SQLite已經包含在python中,所以你不須要安裝任何東西來支持你的數據庫。

(注意:若是你使用的是postgreSQL或者是mysql,肯定你已經建立了相關數據庫,你能夠在數據庫交互提示上經過」CREATE DATABASE database_name;」完成;若是你使用的SQLite、你沒必要提早建立任何東西,在必要的時候數據庫文件會被自動建立。)

當你在編輯settings.py時,把TIME_ZONE設置成你的時區,默認值是美國中部時區(芝加哥)。

同時,注意文件地步的INSTALL_APPS設置,它列舉全部Django應用程序的名字,它們是已經激活的Django實例。這些應用程序能夠在許多項目中使用,你也能夠打包併發布它們使它可以在別人的項目中也能使用。

默認狀況下,INSTALL_APPS包含下面的應用程序,這些都是Django綁定的:

django.contrib.auth:一個認證系統;

django.contrib.contenttypes:內容類型框架;

django.contrib.sessions:會話框架;

django.contrib.sites:單個Django安裝管理多個站點的框架;

django.contrib.messages:一個消息留言框架;

django.contrib.staticfiles:一個管理靜態文件的框架;

爲了方便通常狀況,這些應用程序默認狀況下被自動包含了。

每一個應用程序至少用到了一個數據庫的表,所以,咱們須要建立數據庫的表,這樣咱們才能使用它們。爲了這樣作,運行下面的命令:python manage.py syncdb。

syncdb命令查看INSTALLED_APPS設置而後根據settings.py文件裏數據庫設置建立必要的數據庫表,你將會看到每一個表被建立的信息,接下來你將會得到一個提示問你是否須要建立認證系統的超級帳戶,去作吧。

若是你感興趣,你能夠運行數據庫的命令行,而且輸入\dt(PostgreSQL),SHOW TABLES;(MySQL),或者.schema(SQLite)來顯示Django建立的表。

(對於極簡影像派藝術家:就像咱們上面說到的同樣,默認程序已經包含了一半狀況,但不是每一個人都須要的。若是你不須要它們全部或者部分,你能夠在運行syncdb前在INSATALLED_APPS自由的註釋掉或者刪掉相關行,syncdb命令將只會建立INSTALLED_APPS中應用程序的表。)

4、建立模型(models)

如今,你的環境——一個項目——已經創建i來了,你應該開始作一些事情了。

你用Django寫的每一個程序都是由python包組成的,某些在python路徑下,他們遵行相關公約。Django自帶了一個自動生成一個應用程序基本目錄結構的功能,所以你能夠不用關注建立目錄而只專心寫代碼。

(項目VS應用程序:一個項目和一個應用程序有什麼區別呢?一個應用程序是一個作一些事情的網絡應用程序——好比說,一個網絡博客系統,一個公共唱片記錄的數據庫或者是一個簡單的調查程序。一個項目是對特定的網站的一些列配置和應用程序的集合。一個項目能夠包含多個應用程序,一個應用程序能夠在多個項目中。)

你的應用程序能夠存在在你python路徑下任何地方。在這個教程中,咱們將會在manage.py文件的邊上建立咱們的調查應用程序這樣他就能夠做爲項目本身頂層模塊被引用(而不是一個mysite的子模塊)。

爲了建立你的應用程序,肯定你在和manage.py同一個目錄下,而後輸入命令:python manage.py startapp polls,這將建立一個polls目錄,它的佈局是這樣的:

polls/

    __init__.py

    models.py

    tests.py

    views.py

這個命令結構將容納投票應用程序。

寫網絡應用程序的第一步是定義模型(models)——從本質上來講,就是你的帶有額外元數據的數據庫佈局。

(哲學:一個模型是你數據的一個單個的,肯定的本源。它包含了你存儲數據的必要的空間和行爲。Django遵行DRY原則,這個目標是在一個地方定義你的數據模型而後自動導出來自它的東西。)

在咱們簡單的調查程序中,我麼你建立了兩個模型:polls和choices,一個調查有一個問題和一個公開日期,一個選擇有兩個空間:選擇的內容和投票標籤。每一個選擇都和一個調查相關聯。

這些概念能夠經過簡單的python類展示出來,編輯polls/models.py文件成下面的樣子:

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()
代碼是坦白明瞭的。每一個模型由一個繼承自django.db.models.Model的類表示,每一個模型有一系列類變量,每一個變量都表明模型中的一個數據庫空間(表中的列)。

每一個空間有一個Field類實例表示——好比說CharField表明字符空間,DateTimeField表明日期。這將告訴Django每一個數據空間是什麼類型。

每一個Field實例的名字(好比說question或者pub_date)都是空間的名字,他們是以機器友好的格式存在的。你能夠在你的pyhton代碼中用這個值,你的數據庫將會把它做爲列的名字。

你能夠用一個額外的第一個位置的參數把Field設計成一我的類可讀的名稱。這通常用在Django內省部分的一隊,併兼做文檔。若是沒有提供這個空間,Django將會用機器可讀的名字。這個例子中,咱們爲Poll.pub_date只定義了一我的類可讀的名字。對這個模型中全部其餘的空間,這個空間的機器可讀的名字也能做爲人類可讀的名字。

一些Field類有須要的元素。好比說,CharField要求你給他一個max_length。這不只在數據庫架構中用到,也在驗證中用到,咱們很快就會看到。、

最後,用ForeignKey定義關係,它告訴Django每一個Choice關聯到單個Poll。Django支持全部通常的數據庫關係:多對一,多對多和一對一。

4、激活模型

那一小段模型代碼給Django許多信息,有這些信息,Django就能:

    爲這個應用程序建立一個數據庫構架(CREATE TABLE 表述);

    爲訪問Poll和Choice對象建立基於python的數據庫訪問API;

可是首先咱們應該告訴咱們的項目polls應用程序已經安裝了。

(哲學:Django應用程序是」可插入的「,你能夠在多個項目中用一個應用程序,你也能夠發佈應用程序,由於他們不必綁定在一個給定的Django安裝上。)

再次編輯settings.py文件,修改INSTALLED_APPS設置包含字符串」polls「,這樣它就看起來像這樣:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'polls',
)
如今Django知道包含polls應用程序。讓咱們運行其餘的命令:python manage.py sql polls,你應該看到相似於下面的信息(CREATE TABLE SQL關於polls應用程序的描述):
BEGIN;
CREATE TABLE "polls_poll" (
    "id" serial NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id") DEFERRABLE INITIALLY DEFERRED,
    "choice" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
COMMIT;
注意下面事項:

    根據你使用的數據庫,輸出可能不同;

    表的名字是由應用程序的名字(polls)和模型——poll和choice——的小寫名字自動生成的(你能夠override這種作法);

    主鍵(IDs)自動增長(你能夠override這種作法);

    默認習慣,Django追加」_id「到主鍵空間名字(你也能夠override這種作法);

    外鍵是經過REFERENCES描述來明確關係的;

    對你如今使用的數據庫來講,這是可定作的,所以明確的數據庫空間類型好比說auto_increment(MySQL), serial(PostgreSQL)或者integer primary key(SQLite)會自動爲你處理掉。空間名字的引號也是同樣的——好比說,用雙引號或者單引號。這篇教程的做者是用PostgreSQL,所以離子的輸出時PostgreSQL語法;

    sql命令事實上不在你的數據庫中運行SQL——它只是向屏幕打印sql命令,這樣你能夠看到Django的SQL是怎樣要求的。若是你想的話,你也能夠複製而後黏貼這些SQL到你的數據庫提示下。而後,就像咱們不就將會看到的同樣,Django提供向數據庫提交SQL命令一個更簡單的方式。

若是你有興趣,你也能夠運行下面的命令:

    python manage.py validate——檢查你創建模型結構是的任何錯誤;

    python manage.py sqlcustom polls——輸出一切定義在程序中的常規SQL描述(好比說表的修改和約束);

    python manage.py sqlclear polls——根據數據庫中已經存在的表,輸出關於這個程序DROP TABLE的必要描述;

    python manage.py sqlindexes polls——輸出對這個程序用CREATE INDEX的描述;

    python manage.py sqlall polls——一個關於全部的來自sql,sqlcustom和sqlindexes命令的集合;

查看這些輸出文件能夠幫你理解實際上發生了什麼。

如今再運行syncdb來建立數據庫的模型表:python manage.py syncdb。


syncdb命令對全部在INSTALLED_APPS裏而不在數據庫的應用程序從你電腦運行SQL語句。當你最後一次運行syncdb時,它建立了全部的表,而且對全部程序的初始化的數據和索引已經增長到你的項目。syncdb語句能夠在任什麼時候候被調用,並且它只建立不存在的表。

更多關於manage.py能作什麼的信息能夠閱讀django-admin.py文檔。

5、和API玩

如今,讓咱們跳進python交互腳本和Django提供的API玩。爲了召喚python腳本,使用下面命令:python manage.py shell。咱們用這個命令而不是直接輸入」python「,由於namage.py會設置DJANGO_SETTINGS_MODULE環境變量,它會把Django的python導入路徑給settings.py文件。

(繞過manage.py:若是你不喜歡使用manage.py,沒問題。只需設置DJANGO_SETTINGS_MODULE環境變量爲mysite.settings而後從和manage.py在相同目錄的地方運行python(或者確保目錄是在python路徑上,這樣import mysite有效。)更多信息請參考django-admin.py文檔。)

當你在shell腳本時,探索數據庫的API:

>>> from polls.models import Poll, Choice   # Import the model classes we just wrote.

# No polls are in the system yet.
>>> Poll.objects.all()
[]

# Create a new Poll.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> p = Poll(question="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> p.save()

# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you're using. That's no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> p.id
1

# Access database columns via Python attributes.
>>> p.question
"What's new?"
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> p.question = "What's up?"
>>> p.save()

# objects.all() displays all the polls in the database.
>>> Poll.objects.all()
[<Poll: Poll object>]
等一下子,<Poll:Poll object>顯然是對這個對象不友好的表示,讓咱們經過編輯model(在polls/models.py文件)給Poll和Choice增長一個__unicode__()方法來修復它:
class Poll(models.Model):
    # ...
    def __unicode__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __unicode__(self):
        return self.choice

向模型增長__unicode__()方法很重要,不只僅是爲了你處理交互提示時的正常神智,也由於對象表明在整個Django自動生成admin是也會用到。

(爲何是__unicode__()而不是__str__()?:若是你對python熟悉的話,你可能有向你的類增長__str__()方法的習慣,而不是__unicode__()。咱們這裏使用__unicode__()由於Django模型默認處理Uniocde,數據庫中全部儲存的數據在返回時都被轉換成Unicode。Django模型有一個默認的__str__()方法,它調用__unicode__()方法把結果轉化成UTF-8的字符串。這意味着unicode(q)將返回一個Unicode字符串,str(q)返回一個正常的用utf-8編碼的字符串。若是這些都讓你費解的話,你只要記住向你的模型增長__unicode__()方法。運氣好的話,事情應該只爲你工做。)

注意這些常規python方法,讓咱們增長一個定製的方法,只是爲了演示:

import datetime
from django.utils import timezone
# ...
class Poll(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
注意增長import datetime和from django.utils import timezone,他們分別的參照python標準datetime庫和django.utils.timezone的Django的時區相關的實用程序。若是你對python中處理時區不熟悉,你能夠在時區支持文檔中瞭解更多。

保存這些改變而後運行python manage.py shell再開始一個新的python交互式shell腳本:

>>> from polls.models import Poll, Choice

# Make sure our __unicode__() addition worked.
>>> Poll.objects.all()
[<Poll: What's up?>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]

# Get the poll that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Poll.objects.get(pub_date__year=current_year)
<Poll: What's up?>

>>> Poll.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Poll 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 Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: What's up?>

# Make sure our custom method worked.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True

# Give the Poll 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 poll's choices) which can be accessed via the API.
>>> p = Poll.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> p.choice_set.all()
[]

# Create three choices.
>>> p.choice_set.create(choice='Not much', votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice='The sky', votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)

# Choice objects have API access to their related Poll objects.
>>> c.poll
<Poll: What's up?>

# And vice versa: Poll objects get access to Choice objects.
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.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 poll whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(poll__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# Let's delete one of the choices. Use delete() for that.
>>> c = p.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete()
模型相關的更多細節請參考Accessing related objects。更多關於如何使用雙下劃線經過API強調空間查找,請參考Field lookups。關於數據庫API更完整的細節,請參考Database API reference。

當你以爲對這些API適應以後,讀第二部分教程瞭解Django的自動管理。

《第一部分,完!》

相關文章
相關標籤/搜索