Django教程:第一個Django應用程序(1部分)

  •  

  • 請看實例。本教程中將建立一個基本的投票應用。node

     

     

     

    它由兩部分組成:查看投票的結果和投票的公共網站;添加、修改和刪除投票的管理站點。python

     

    請先確認Django已經安裝並檢查版本號:mysql

     

    # python -c "import django;print(django.get_version())"web

     

    1.5.1sql

     

    本教程基於 Django 1.5.* 和Python 2.x。shell

     

    尋求幫助:django-users或#django onirc.freenode.net 數據庫

     

    建立projectdjango

     

    django-admin.py startproject mysite瀏覽器

     

    這將在當前目錄建立 mysite 目錄。注意須要避免使用 python 保留字或 Django 組件名做爲project名稱。尤爲注意不要使用如:django (與 Django 自己會衝突) 或者 test (與 Python 內置的包名會衝突).服務器

     

             Project建立的文件以下:

     

    # ls -R mysite

     

    mysite:

     

    manage.py mysite

     

     

     

    mysite/mysite:

     

    __init__.py  settings.py urls.py  wsgi.py

     

     

     

    l 外層 mysite根目錄是你project容器。對Django該目錄名並不重要; 你能夠重命名。

     

    l manage.py: 可以讓你以各類方式與Django項目進行交互命令行工具。你能夠在 django-admin.py和manage.py 中查看manage.py 更多信息。

     

    l 內層 mysite目錄是project的實際 Python 包。

     

    l mysite/__init__.py: 包初始化文件,默認爲空.

     

    l mysite/settings.py: 配置文件。

     

    l mysite/urls.py: project的 URL 聲明。

     

    l mysite/wsgi.py: 一個 WSGI 兼容的 Web 服務器的入口,以便運行你的項目。

     

     

     

    開發服務器

     

             如今已經有一個簡單的服務器了。進入外層mysite目錄,執行

     

    # python manage.py runserver

     

    Validating models...

     

     

     

    0 errors found

     

    September 22, 2013 - 01:04:43

     

    Django version 1.5.4, using settings'mysite.settings'

     

    Development server is running athttp://127.0.0.1:8000/

     

    Quit the server with CONTROL-C.

     

    這樣就啓動了 Django開發服務器,一個純Python的輕量級 Web 服務器。Django 包含了它。這樣在產品投入使用以前沒必要配置產品服務器例如 Apache,方便更加快速開發。

     

     

     

    **不要** 在任何生產環境中使用此服務器。它僅適用於開發。(Django提供的是 Web 框架的,而不是 Web 服務器。)

     

     

     

    服務器運行時,在你Web 瀏覽器中訪問http://127.0.0.1:8000/ 。你會看到 「Welcome toDjango」頁面,代表開發服務器工做正常。

     

     

     

    默認runserver 命令啓動的開發服務器只監聽localIP 的 8000 端口。

     

    改變端口:

     

    python manage.py runserver 8080

     

    改變IP ,須要和端口號一塊兒傳遞。所以,要監聽全部外部 IP 地址:

     

    python manage.py runserver 0.0.0.0:8000

     

    更多資料參見runserver 。

     

     

     

    數據庫設置

     

    編輯 mysite/settings.py 。這是一個普通的 Python 模塊,包含了Django 模塊級變量的設置。更改 DATABASES 中 'default' 下的如下鍵的值,以匹配您的數據庫鏈接設置。

     

     

     

    l ENGINE –  'django.db.backends.postgresql_psycopg2'或'django.db.backends.mysql',或'django.db.backends.sqlite3', 'django.db.backends.oracle' , 更多的參見alsoavailable。

     

     

     

    l NAME – 數據庫名。對 SQLite,是絕對路徑的文件名(好像project下面文件直接輸入文件名就能夠,由於在GAE,SAE等雲平臺,是不太可能知道真實路徑的?);若是該文件不存在,它會在第一次同步數據庫時自動建立(見下文)。

     

     

     

    當指定路徑時,老是使用斜槓,即便是Windows 下(例如:``C:/homes/user/mysite/sqlite3.db``) 。

     

     

     

    l USER – 用戶名 ( SQLite 下不須要) 。

     

    l PASSWORD – 密碼 ( SQLite 下不須要) 。

     

    l HOST – 數據庫主機地址。若是是同一臺物理機器,請將此處保留爲空 (或者設置爲 127.0.0.1) ( SQLite 下不須要) 。查看HOST瞭解詳細信息。

     

     

     

    若是你是數據庫新手,咱們建議使用 SQLite ,將 ENGINE 改成 'django.db.backends.sqlite3' 而且將 NAME 設置爲你想存放數據庫的地方。 Python 內置了SQLite,不須要額外安裝。

     

     

     

    當你編輯 settings.py 時,將 TIME_ZONE 修改成你所在的時區。默認值是美國中央時區(芝加哥)。

     

    中國通常設置爲TIME_ZONE = 'Asia/Shanghai'。

     

     

     

    同時,注意文件底部的 INSTALLED_APPS 設置。它保存了當前 Django 實例已激活的全部 Django 應用。每一個應用能夠被多個項目使用,並且你能夠打包和分發給其餘人。

     

     

     

    默認狀況下,:setting:INSTALLED_APPS 包含如下應用,這些都是由 Django 提供的:

     

     

     

    l     django.contrib.auth – 身份驗證系統。

     

    l     django.contrib.contenttypes – 內容類型框架。

     

    l     django.contrib.sessions – session 框架。

     

    l     django.contrib.sites – 網站管理框架。

     

    l     django.contrib.messages – 消息框架。

     

    l     django.contrib.staticfiles – 靜態文件管理框架。

     

     

     

    全部這些應用中每一個應用至少使用一個數據庫表,因此在使用它們以前須要建立數據庫中的表:

     

    python manage.py syncdb

     

     

     

    syncdb 命令參照 settings.py 文件中的INSTALLED_APPS 設置建立必要的數據庫表。每建立一個數據庫表你都會看到一條消息,接着你會看到一個提示詢問你是否想爲驗證系統內建立個超級用戶。咱們選擇須要。

     

     

     

    數據庫命令行下輸入:``dt``(PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 可列出Django 所建立的表。

     

     

     

    建立模型

     

    Djaong每一個應用都是由Python 包,這些在Python path 中而且遵循django命名規範。 Django 有工具能夠自動生成應用的基本目錄架構,你能夠專一於編寫代碼而不是去建立目錄。

     

    項目 ( Projects ) vs. 應用 ( apps )

     

    項目與應用之間有什麼不一樣之處?應用是一個提供具體功能的 Web 應用– 例如:博客系統、公共記錄的數據庫或簡單的投票系統。項目是特定的 Web 網站相關的配置和其應用的集合。一個項目能夠包含多個應用。一個應用能夠在多個項目中使用。

     

     

     

    你的應用能夠存放在 Python path 中的任何位置。在本教程中,經過你的 manage.py 文件建立投票應用,以便它能夠做爲頂層模塊導入,而不是做爲 mysite 的子模塊。

     

     

     

    要建立你的應用,請確認與 manage.py 文件在同一的目錄下並輸入如下命令:

     

     

     

    python manage.py startapp polls

     

    這將建立一個 polls 目錄,其展開的樣子以下所示::

     

     

     

    polls/

     

       __init__.py

     

       models.py

     

       tests.py

     

       views.py

     

     

     

    編寫數據庫支持的 Web 應用的第一步是定義模型– 從本質是數據庫設計及其元數據。

     

    模型是有關你數據的惟一且明確的數據源。它包含了你所要存儲的數據的基本字段和行爲。 Django遵循DRY 原則 。目標是爲在一個地方定義你的數據模型就可從中自動獲取數據。

     

     

     

    在這簡單的投票應用中,咱們將建立兩個模型: Poll 和 Choice``。``Poll 有問題和發佈日期兩個字段。``Choice`` 有兩個字段:選項 ( choice ) 的文本內容和投票數。每個 Choice 都與一個 Poll 關聯。

     

     

     

    這些概念都由簡單的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_text = models.CharField(max_length=200)

     

       votes = models.IntegerField(default=0)

     

    代碼很簡單。每一個模型都由繼承自 django.db.models.Model的類來描述。 每一個模型都有一些類變量,每個類變量都表明了一個數據庫字段。

     

     

     

    每一個字段由一個 Field的實例來表現 – 好比 CharField 表示字符類型的字段和DateTimeField 表示日期時間型的字段。這會告訴 Django 每一個字段都保存了什麼類型的數據。

     

    每一個 Field 實例的名字就是字段的名字(如: question 或者 pub_date ),其格式接近機器語言。在你的 Python 的代碼中會使用這個值,而你的數據庫會將這個值做爲列名。

     

     

     

    初始化 Field 實例時第一個可選參數能夠設立用戶友好的名字。Django的內省會使用它,文檔有更多的使用以提升可讀性。若該字段未提供,Django 將使用機器語言。

     

     

     

    一些 Field 類有必選參數, 例如 CharField 須要你指定max_length`。

     

     Field 實例能夠有不一樣的可選參數; 在本例中,咱們將votes 的 default 的值設爲 0 。

     

     

     

    最後,注意咱們使用了ForeignKey 定義了一個關聯。它告訴 Django 每個``Choice`` 關聯一個 Poll 。 Django 支持常見數據庫的全部關聯:多對一,多對多和一對一。

     

     

     

    激活模型

     

    模型代碼提供給 Django 大量信息。Django 就能夠作:

     

     

     

    l 爲應用建立數據庫模式 (CREATE TABLE 語句) 。

     

    l 建立 Python 訪問Poll 和 Choice 對象的數據庫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',

     

    )

     

    注意polss要有引號和逗號,如今 Django 已經知道包含了 polls 應用。讓咱們運行以下命令:

     

    python manage.py sql polls

     

    你將看到相似以下所示內容 ( 有關投票應用的 CREATE TABLE SQL 語句 ):

     

    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_text" varchar(200) NOT NULL,

     

       "votes" integer NOT NULL

     

    );

     

    COMMIT;

     

    請注意:

     

     

     

    l 具體的輸出根據數據庫會有所不一樣。

     

    l 表名是自動生成,組合應用名 (polls) 和小寫的模型名(poll 和 choice),可重載此行爲。

     

    l 主鍵 (IDs) 是自動添加的,可重載。

     

    l 一般Django 會在外鍵字段名上附加 "_id" ,可重載。

     

    l 外鍵由 REFERENCES 語句顯示聲明。

     

    l SQL 語句時和數據庫類型相關,會爲你自動處理特定於數據庫的字段,例如 auto_increment (MySQL), serial (PostgreSQL), 或 or integerprimary key (SQLite) 。上面輸出的是 PostgreSQL 的語法。

     

    l sql沒有數據庫中真正執行,僅僅顯示SQL語句。

     

    其餘命令:

     

     

     

    python manage.py validate – 檢查在模型錯誤。

     

    python manage.py sqlcustom polls – 輸出應用自定義的SQL 語句 (©例如表修改或約束) 。

     

    python manage.py sqlclear polls –若是表已經存在輸出必要的DROP TABLE 。

     

    python manage.py sqlindexes polls– 爲應用輸出 CREATEINDEX 語句。

     

    python manage.py sqlall polls –等同於sql, sqlcustom,和 sqlindexes之和。

     

     

     

    再次運行 syncdb 命令在數據庫中建立這些模型對應的表:

     

     

     

    python manage.py syncdb

     

     syncdb 命令會給沒有數據庫表的開啓執行sqlall 操做。爲上次執行 syncdb 命令之後的添加的應用建立表、初始化數據和索引。 syncdb 命令能夠隨時調用,它只會建立不存在的表。

     

     

     

    瞭解 manage.py 工具更多的功能參見。

     

     

     

     

     

    玩轉API

     

     

     

    Python 的交互式 shell 中也能夠玩轉 DjangoAPI 。執行:

     

    python manage.py shell

     

    manage.py 設置了DJANGO_SETTINGS_MODULE 環境變量,導入了mysite/settings.py中的相關設置。這是和直接敲python的區別。

     

     

     

    >>> from polls.models importPoll, Choice   # Import themodel 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 thedefault settings file, so

     

    Django expects a datetime with tzinfofor pub_date. Use timezone.now()

     

    # instead of datetime.datetime.now() andit will do the right thing.

     

    >>> from django.utils importtimezone

     

    >>> p = Poll(question="What'snew?", pub_date=timezone.now())

     

     

     

    # Save the object into the database. Youhave to call save() explicitly.

     

    >>> p.save()

     

     

     

    # Now it has an ID. Note that this mightsay "1L" instead of "1", depending

     

    # on which database you're using. That'sno biggie; it just means your

     

    # database backend prefers to returnintegers as Python long integer

     

    # objects.

     

    >>> p.id

     

    1

     

     

     

    # Access database columns via Pythonattributes.

     

    >>> p.question

     

    "What's new?"

     

    >>> p.pub_date

     

    datetime.datetime(2012, 2, 26, 13, 0, 0,775217, tzinfo=<UTC>)

     

     

     

    # Change values by changing theattributes, then calling save().

     

    >>> p.question = "What'sup?"

     

    >>> p.save()

     

     

     

    # objects.all() displays all the polls inthe database.

     

    >>> Poll.objects.all()

     

    [<Poll: Poll object>]

     

    ``<Poll: Poll object>`` 的顯示比較醜,且沒有實際意義。 編輯 polls 模型( 在 polls/models.py 文件中 ) 而且給 Poll 和 Choice 都添加一個__unicode__() 方法:

     

     

     

    class Poll(models.Model):

     

       # ...

     

       def __unicode__(self):  # Python3: def __str__(self):

     

           return self.question

     

     

     

    class Choice(models.Model):

     

       # ...

     

       def __unicode__(self):  # Python3: def __str__(self):

     

           return self.choice_text

     

    添加 __unicode__() 方法是至關重要的,不只讓你在命令行下有明確提示,並且在 Django 自動生成的管理界面中也有好的對象展現。

     

     

     

    Django 模型默認處理的是Unicode 格式。全部數據庫中的數據返回時都會轉換爲 Unicode。

     

    Django 模型有個默認的__str__() 方法會調用 __unicode__() 並將結果轉換爲 UTF-8 編碼的字符串。這就意味着 unicode(p) 會返回一個 Unicode 字符串,而 str(p) 會返回一個以 UTF-8 編碼的普通字符串。

     

    還能夠添加自定義方法, 好比:

     

     

     

    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)

     

    時區相關的內容,參見time zone support docs。

     

    保存後從新執行python manage.py shell:

     

    >>> from polls.models importPoll, Choice

     

     

     

    # Make sure our __unicode__() additionworked.

     

    >>> Poll.objects.all()

     

    [<Poll: What's up?>]

     

     

     

    Django provides a rich database lookupAPI 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 thisyear.

     

    >>> from django.utils importtimezone

     

    >>> current_year =timezone.now().year

     

    >>>Poll.objects.get(pub_date__year=current_year)

     

    <Poll: What's up?>

     

     

     

    # Request an ID that doesn't exist, thiswill raise an exception.

     

    >>> Poll.objects.get(id=2)

     

    Traceback (most recent call last):

     

       ...

     

    DoesNotExist: Poll matching query does notexist. Lookup parameters were {'id': 2}

     

     

     

    # Lookup by a primary key is the mostcommon case, so Django provides a

     

    # shortcut for primary-key exact lookups.

     

    # The following is identical toPoll.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. Thecreate call constructs a new

     

    # Choice object, does the INSERTstatement, adds the choice to the set

     

    # of available choices and returns the newChoice object. Django creates

     

    # a set to hold the "other side"of a ForeignKey relation

     

    # (e.g. a poll's choices) which can beaccessed via the API.

     

    >>> p = Poll.objects.get(pk=1)

     

     

     

    # Display any choices from the relatedobject set -- none so far.

     

    >>> p.choice_set.all()

     

    []

     

     

     

    # Create three choices.

     

    >>>p.choice_set.create(choice_text='Not much', votes=0)

     

    <Choice: Not much>

     

    >>>p.choice_set.create(choice_text='The sky', votes=0)

     

    <Choice: The sky>

     

    >>> c =p.choice_set.create(choice_text='Just hacking again', votes=0)

     

     

     

    # Choice objects have API access to theirrelated Poll objects.

     

    >>> c.poll

     

    <Poll: What's up?>

     

     

     

    # And vice versa: Poll objects get accessto Choice objects.

     

    >>> p.choice_set.all()

     

    [<Choice: Not much>, <Choice: Thesky>, <Choice: Just hacking again>]

     

    >>> p.choice_set.count()

     

    3

     

     

     

    # The API automatically followsrelationships as far as you need.

     

    # Use double underscores to separaterelationships.

     

    # This works as many levels deep as youwant; there's no limit.

     

    # Find all Choices for any poll whosepub_date is in this year

     

    # (reusing the 'current_year' variable wecreated above).

     

    >>>Choice.objects.filter(poll__pub_date__year=current_year)

     

    [<Choice: Not much>, <Choice: Thesky>, <Choice: Just hacking again>]

     

     

     

    # Let's delete one of the choices. Usedelete() for that.

     

    >>> c =p.choice_set.filter(choice_text__startswith='Just hacking')

     

    >>> c.delete()

     

    欲瞭解更多有關模型關係的信息,參見Accessing related objects. 。欲瞭解更多有關如何使用雙下劃線來經過 API 執行字段查詢的,參見Field lookups。 如需完整的數據庫 API 信息,參見Database API reference。

相關文章
相關標籤/搜索