“全能”選手—Django 1.10文檔中文版Part1


歡迎大家訪問我的個人網站《劉江的博客和教程》:www.liujiangblog.com

主要分享Python 及Django教程以及相關的博客


本文是博主翻譯的Django1.10版本官方文檔的第一部分,如時間充裕,爭取一直翻譯下去,經驗不足,或有錯漏,敬請指正。
另外對於公開文檔進行翻譯的版權問題不是很清楚,如有侵權請聯系我!

另外,要轉載該系列翻譯文章,也請聯系博主。

第二部分傳送門

第三部分傳送門

第四部分傳送門

3.2 模型和數據庫Models and databases

3.2.2 查詢操作making queries

3.3.8 會話sessions

目錄

第一章、Django1.10文檔組成結構
1.1 獲取幫助
1.2 文檔的組織形式
1.3 第一步
1.4 模型層
1.5 視圖層
1.6 模板層
1.7 表單
1.8 開發流程
1.9 admin站點
1.10 安全性
1.11 國際化和本地化
1.12 性能和優化
1.13 Python兼容性
1.14 地理框架
1.15 常用WEB應用工具
1.16 其它核心功能
1.17 Django開源項目

第二章、起步
2.1 Django速覽

  • 2.1.1 設計你的模型model
  • 2.1.2 安裝model
  • 2.1.3 使用API
  • 2.1.4 功能強大的動態admin后台管理界面
  • 2.1.5 設計你的路由系統URLs
  • 2.1.6 編寫你的視圖views
  • 2.1.7 設計你的模板
  • 2.1.8 總結

2.2 快速安裝指南

  • 2.2.1 安裝Python
  • 2.2.2 安裝Django
  • 2.2.3 安裝驗證

2.3 第一個Django app,Part 1:請求和響應

  • 2.3.1 創建project
  • 2.3.2 開發服務器development server
  • 2.3.3 創建投票程序(polls app)
  • 2.3.4 編寫視圖

2.4 第一個Django app,Part 2:模型和admin站點

  • 2.4.1 數據庫安裝
  • 2.4.2 創建模型models
  • 2.4.3 激活模型
  • 2.4.4 學會使用API
  • 2.4.5 Django admin站點介紹

第一章、Django1.10文檔組成結構

1.1 獲取幫助

獲取幫助的方式:

  • 參考第5.1節的FAQ,這里包含許多常見問題的回答
  • 查找特定的信息?嘗試一下智能檢索、混合索引或者內容詳細表
  • 在10.2.1的DJango用戶郵件列表中查找信息或發布問題
  • 在django的IRC頻道提問或者查找IRC日志看看是否已經有類似問題
  • 報告DJango中的bug

1.2 文檔的組織形式

Django有許多文檔,一個高層次的概覽有助於你快速找到想要的信息:

  • 入門教程:手把手的教會你創建一個WEB應用。如果你是個Django或者WEB應用開發者新手,從這里開始學習是個不錯的選擇。也可以先看看下面的“第一步”。
  • 主題向導:討論一些比較關鍵的主題和概念,屬於比較高的水平,提供一些有用的背景信息和解釋。
  • 參考指南:包含API的使用指導和一些Django內核的其它方面。主要描述Django是怎么工作的,如何使用它。學習這部分的前提是你需要對一些關鍵概念具有基本的理解和掌握。
  • “怎么辦”向導:主要討論一些關鍵的問題和使用場景。比入門教程更深入,需要你對Django的工作機制有一定的了解。

1.3 第一步

如果你是Django或程序員新手,那么從這里開始吧!

  • 從零開始:概覽 | 安裝
  • 入門教程:Part 1:請求和響應 | Part 2:模型和admin站點 | Part 3:視圖和模板 | Part 4:表單和泛型 | Part 5:測試 | Part 6:靜態文件 | Part 7:自定制admin站點
  • 高級教程: 如何編寫可重用的應用 | 編寫你的第一個Django補丁

1.4 模型層

Django提供了一個抽象的模型層,用於組織和操縱你的WEB應用數據。

  • 模型:模型介紹 | 字段類型 | Meta選項 | 模型類
  • 查詢結果集:執行查詢 | 查詢結果集方法參考 | 查詢表達式
  • 模型實例: 實例方法 | 訪問關系對象
  • 遷移: 遷移介紹 | 操作參考 | 計划編輯 | 編寫遷移
  • 高級: 管理器 | 原生SQL | 事務 | 聚合 | 查找 | 自定義字段 | 多數據庫 | 自定義查詢 | 查詢表達式 | 條件表達式 | 數據庫函數
  • 其它:支持的數據庫 | 遺留數據庫 | 提供初始化數據 | 優化數據庫訪問 | PostgreSQL特有

1.5 視圖層

Django將封裝響應用戶請求邏輯和返回數據稱為“視圖”。在下面的列表中,你能找到所有和視圖相關的內容:

  • 基礎: 路由配置 | 視圖函數 | 快捷方式 | 裝飾器
  • 參考: 內置視圖 | 請求/響應對象 | 模板響應對象
  • 文件上傳: 概覽 | 文件對象 | 儲存API | 管理文件 | 自定義存儲
  • 基類視圖: 概覽 | 內置顯示視圖 | 內置編輯視圖 | 混合使用 | API參考 | 分類索引
  • 高級: 生成CSV | 生成PDF
  • 中間件:概覽 | 內置中間件類

1.6 模板層

模板層提供一種人性化的語法,用於渲染展示給用戶的內容,主要內容包括下列:

  • 基礎:概覽
  • 對於設計師:語言概覽 | 內置標簽和過濾器 | 人性化
  • 對於程序員: 模板API | 自定義標簽和過濾器

1.7 表單

Django 提供了一個內容豐富的框架可便利地創建表單及操作表單數據。

  • 基礎: 概覽 | 表單 API | 內置字段 | 內置小工具
  • 高級: 模型表單 | 表單外觀 | 表單集 | 自定義驗證

1.8 開發流程

學習不同的組件和工具,幫助你開發和測試Django應用。

  • 設置:概覽 | 全部設置列表
  • 應用: 概覽
  • 異常:概覽
  • Django-admin和manage.py:概覽 | 添加自定義命令
  • 測試:介紹 | 編寫和運行測試 | 導入測試工具 | 高級主題
  • 部署:概覽 | WSGI服務器 | 部署靜態文件 | 通過郵件跟蹤代碼錯誤

1.9 admin站點

在這里,你可以找到Django中最受歡迎的功能模塊——admin站點的一切:

  • admin站點
  • admin動作
  • admin文檔生成器

1.10 安全性

開發 Web 應用時安全是最重要一個的主題,Django 提供了多重保護工具和機制:

  • 安全概覽
  • 披露的Django安全問題
  • 點擊劫持的防護
  • 跨站請求偽造防護
  • 加密簽名
  • 安全中間件

1.11 國際化和本地化

Django 提供了一個強大的國際化和本地化框架,以協助您開發支持多國語言和世界各地區的應用:

  • 概覽 | 國際化 |本地化 | 本地WEB UI 格式化和表單輸入
  • 時區

1.12 性能和優化

有許技術和工具可以幫助你的代碼運行得更加高效、快速,占用更少的系統資源。

  • 性能和優化概覽

1.13 Python兼容性

Django 希望兼容多個不同特性和版本的 Python:

  • Jython支持
  • Python3 兼容性

1.14 地理框架

GeoDjango 想要做一個世界級的地理Web框架。 它的目標是盡可能輕松的構建GIS Web 應用和發揮空間數據的能力。

1.15 常用WEB應用工具

Django 為開發Web應用提供了多種常見的工具:

  • 身份認證:概覽 | 使用認證系統 | 密碼管理 | 自定義認證 | API參考
  • 緩存
  • 日志
  • 發送郵件
  • 聯合供稿(RSS/Atom)
  • 分頁
  • 消息框架
  • 序列化
  • 會話
  • 站點地圖
  • 靜態文件管理
  • 數據驗證

1.16 其它核心功能

Django的其它核心功能包括:

  • 按需處理內容
  • 內容類型和泛型關系
  • 簡單頁面
  • 重定向
  • 信號
  • 系統檢查框架
  • 站點框架
  • 在 Django 中使用 Unicode

1.17 Django開源項目

下面是Django項目本身的開發進程和如何做出貢獻相關:

  • 社區: 如何參與 | 發布過程 | 團隊組織 | 團隊會議 | 主要人員 | 源碼倉庫 | 安全策略 | 郵件列表
  • 設計理念: 概述
  • 文檔: 關於本文檔
  • 第三方發行: 概述
  • Django 的過去: API 穩定性 | 發行說明和升級說明 | 功能棄用時間軸

第二章、起步

2.1 Django速覽

Django的開發背景是快節奏的新聞編輯室環境,因此它被設計成一個大而全的web框架,能夠快速簡單的完成任務。本節將快速介紹如何利用Django搭建一個數據庫驅動的WEB應用。
它不會有太多的技術細節,只是讓你理解Django是如何工作的。

2.1.1 設計你的模型model

Django提供了ORM,通過它,你能直接使用Python代碼來描述你的數據庫設計。下面是一個例子:

# mysite/news/models.py

from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)
    def __str__(self): # __unicode__ on Python 2
    return self.full_name
class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
    def __str__(self): # __unicode__ on Python 2
    return self.headline

2.1.2 安裝model

接下來,進入Django命令行工具,創建數據庫表:
$ python manage.py migrate
migrate命令查找所有可用的model,如果它還沒有在數據庫中存在,將根據model創建相應的表。注:也許你需要先執行$ python manage.py makemigrations命令。

2.1.3 使用API

Django為你提供了大量的方便的數據庫操作API,無需你編寫額外的代碼。下面是個例子:

# Import the models we created from our "news" app
>>> from news.models import Reporter, Article
# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>
# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Now it has an ID.
>>> r.id
1
# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>
# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'
# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.
# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()
# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>
# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'
# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>
# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>
# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()
# Delete an object with delete().
>>> r.delete()

2.1.4 功能強大的動態admin后台管理界面

Django包含一個功能強大的admin后台管理模塊,使用方便,要素齊全。有助於你快速開發。你只需要在下面兩個文件中寫幾句短短的代碼:
mysite/news/models.py



from django.db import models
class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

mysite/news/admin.py

from django.contrib import admin
from . import models

admin.site.register(models.Article)

2.1.5 設計你的路由系統URLs

Django主張干凈、優雅的路由設計,不建議在路由中出現類似.php或.asp之類的字眼。

路由都寫在URLconf文件中,它建立起URL匹配模式和python毀掉函數之間的映射,起到了解耦的作用。下面是一個例子:
mysite/news/urls.py

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

Django通過正則表達式,分析訪問請求的url地址,匹配相應的views,調用對應的函數。

2.1.6 編寫你的視圖views

每一個視圖都必須做下面兩件事情之一:返回一個包含請求頁面數據的HttoResponse對象或者彈出一個類似404頁面的異常。

通常,視圖通過參數獲取數據,並利用它們渲染加載的模板。下面是一個例子:
mysite/news/views.py

from django.shortcuts import render
from .models import Article
def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

2.1.7 設計你的模板

Django有一個模板查找路徑,在settings文件中,你可以指定路徑列表,Django自動按順序在列表中查找你調用的模板。一個模板看起來是下面這樣的:
mysite/news/templates/news/year_archive.html

{% extends "base.html" %}
{% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
<h1>Articles for {{ year }}</h1>
{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

Django使用自己的模板渲染語法,Jinja2就是參考它設計出來的。雙大括號包含起來的是變量,它將被具體的值替換。圓點不但可以用來查詢屬性,也可以用來調用字典鍵值,列表索引和調用函數。
Django具有模板繼承、導入和加載的概念,分別使用extend、include和load語法。下面是一個基礎模板大概的樣子:
mysite/templates/base.html

{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>

子模板繼承母模板的內容,並加入自己獨有的部分。通過更換母版,可以快速的修改整改站點的外觀和樣式。

2.1.8 總結

Django為你提供了大量的模塊和組件,包括模板系統、模型系統、視圖系統以及其他一些通用組件和專用組件。他們之間都是獨立的,同時也是可選的,你完全可以使用自己的模板、模型、視圖。但是,Django給你提供的是一個集成度高的高效率整體框架,如果你自己的水平不是很高,那建議還是使用Django提供的吧。

2.2 快速安裝指南

在第三章的第一節有詳細的安裝指南,這里只是一個簡單的安裝向導,用於快速搭建環境進入下面的章節。

2.2.1 安裝Python

Django與python版本的對應關系。

Django version Python versions
1.8 2.7, 3.2 (until the end of 2016), 3.3, 3.4, 3.5
1.9, 1.10 2.7, 3.4, 3.5
1.11 2.7, 3.4, 3.5, 3.6
2.0 3.5+

請前往Python官網下載並安裝python。 另外,python和Django自帶輕量級數據庫SQLite3,因此,在學習階段你無需安裝並配置其他的數據庫。

2.2.2 安裝Django

如果你是通過升級的方式安裝Django,那么你需要先卸載舊的版本,具體查看3.1.4節。
你可以通過下面的3種方法安裝Django:

  • 安裝你的操作系統提供的發行版本
  • 安裝官方版本(推薦)
  • 安裝開發版本

這里,請前往Django官網下載最新版本或通過pip3 install django進行安裝。

下面是Django官方對版本的支持策略:


而這是未來發布版本的路線圖:

2.2.3 安裝驗證

進入python環境,輸入下列命令,注意版本號和你新安裝的一致:

>>> import django
>>> print(django.get_version())
1.10

或者使用命令$ python -m django --version查看版本號。

下面,我們將進入官方文檔提供的編寫第一個Django app教程!

2.3 第一個Django app,Part 1:請求和響應

在這個例子中,我們將編寫一個問卷調查網站,它包含下面兩部分:

  • 一個可以讓人們進行投票和查看結果的公開站點
  • 一個讓你可以進行增刪改查的后台admin管理界面

本教程使用Django 1.10 及Python 3.4以上版本!

2.3.1 創建project

進入你指定的某個目錄,運行下面的命令:
$ django-admin startproject mysite
這將在目錄下生成一個mysite目錄,也就是你的這個Django項目的根目錄。它包含了一系列自動生成的目錄和文件,具備各自專有的用途。注意:在給項目命名的時候必須避開Django和Python的保留關鍵字,比如“django”,“test”等,否則會引起沖突和莫名的錯誤。對於mysite的放置位置,不建議放在傳統的/var/wwww目錄下,它會具有一定的數據暴露危險,因此Django建議你將項目文件放在例如/home/mycode類似的位置。
一個新建立的項目結構大概如下:

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

詳細解釋:

  • 外層的mysite/目錄與Django無關,只是你項目的容器,可以任意命名。
  • manage.py:一個命令行工具,用於與Django進行不同方式的交互腳本,非常重要!
  • 內層的mysite/目錄是真正的項目文件包裹目錄,它的名字是你引用內部文件的包名,例如:mysite.urls。
  • mysite/init.py:一個定義包的空文件。
  • mysite/settings.py:項目的主配置文件,非常重要!
  • mysite/urls.py:路由文件,所有的任務都是從這里開始分配,相當於Django驅動站點的內容表格,非常重要!
  • mysite/wsgi.py:一個基於WSGI的web服務器進入點,提供底層的網絡通信功能,通常不用關心。

2.3.2 開發服務器development server

進入mystie目錄,輸入下面的命令:
$ python manage.py runserver
你會看到下面的提示:

Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run `python manage.py migrate' to apply them.
September 07, 2016 - 15:50:53
Django version 1.10, using settings `mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Django提供了一個用於開發的web服務器,使你無需配置一個類似Ngnix的線上服務器,就能讓站點運行起來。但你也不要將開發服務器用於生產環境,它只是一個簡易的測試服務器。
現在,在瀏覽器訪問http://127.0.0.1:8000/,你將看到Django的歡迎陰面,一切OK!
django開發服務器(以后省略)默認運行在內部的8000端口,如果你想指定,請在命令中顯示給出,例如:
$ python manage.py runserver 0.0.0.0:8000
上面:Django將運行在8000端口,整個子網內都將可以訪問,而不是本機。
注意: Django的開發服務器具有自動重載功能,當你的代碼有修改,每隔一段時間服務器將自動更新。但是,有一些例如增加文件的動作,不會觸發服務器重載,這時就需要你自己手動重啟。

2.3.3 創建投票程序(polls app)

app與project的區別:

  • 一個app實現某個功能,比如博客、公共檔案數據庫或者簡單的投票系統;
  • 一個project是配置文件和多個app的集合,他們組合成整個站點;
  • 一個project可以包含多個app;
  • 一個app可以屬於多個project!

app的存放位置可以是任何地點,但是通常我們將它們都放在與manage.py同級目錄下,這樣方便導入文件。

進入mysite目錄,確保與manage.py文件處於同一級,輸入下述命令:
$ python manage.py startapp polls
系統會自動生成 polls目錄,其結構如下:

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

2.3.4 編寫視圖

在polls/views.py文件中,輸入下列代碼:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

為了調用該視圖,我們還需要編寫urlconf。現在,在polls目錄中新建一個文件,名字為urls.py,在其中輸入代碼如下:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

下一步是讓項目的主urls文件指向我們建立的polls這個app獨有的urls文件,你需要先導入include模塊,打開mysite/urls.py文件,代碼如下:

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
    url(r'^admin/', admin.site.urls),
]

include語法相當於二級路由策略,它將接收到的url地址去除了它前面的正則表達式,將剩下的字符串傳遞給下一級路由進行判斷。在路由的章節,有更加詳細的用法指導。
include的背后是一種即插即用的思想。項目根路由不關心具體app的路由策略,只管往指定的二級路由轉發,實現了解耦的特性。app所屬的二級路由可以根據自己的需要隨意編寫,不會和其它的app路由發生沖突。app目錄可以放置在任何位置,而不用修改路由。這是軟件設計里很常見的一種模式。
建議:除了admin路由外,你應該盡量給每個app設計自己獨立的二級路由。

好了,路由也搭建成功,下面我們啟動服務器,然后在瀏覽器中訪問地址http://localhost:8000/polls/。一切正常的話,你將看到“Hello, world. You’re at the polls index.”

url()函數可以傳遞4個參數,其中2個是必須的:regex和view,以及2個可選的參數:kwargs和name。下面是具體的解釋:

regex:
regex是正則表達式的通用縮寫,它是一種匹配字符串或url地址的語法。Django拿着用戶請求的url地址,在urls.py文件中對urlpatterns列表中的每一項條目從頭開始進行逐一對比,一旦遇到匹配項,立即執行該條目映射的視圖函數或二級路由,其后的條目將不再繼續匹配。因此,url路由的編寫順序至關重要!

需要注意的是,regex不會去匹配GET或POST參數或域名,例如對於https://www.example.com/myapp/,regex只嘗試匹配myapp/。對於https://www.example.com/myapp/?page=3,regex也只嘗試匹配myapp/。

如果你想深入研究正則表達式,可以讀一些相關的書籍或專論,但是在Django的實踐中,你不需要多高深的正則表達式知識。

性能注釋:正則表達式會進行預先編譯當URLconf模塊加載的時候,因此它的匹配搜索速度非常快,你通常感覺不到。

view:
當正則表達式匹配到某個條目時,自動將封裝的HttpRequest對象作為第一個參數,正則表達式“捕獲”到的值作為第二個參數,傳遞給該條目指定的視圖。如果是簡單捕獲,那么捕獲值將作為一個位置參數進行傳遞,如果是命名捕獲,那么將作為關鍵字參數進行傳遞。

kwargs:
任意數量的關鍵字參數可以作為一個字典傳遞給目標視圖。

name:
對你的URL進行命名,可以讓你能夠在Django的任意處,尤其是模板內顯式地引用它。相當於給URL取了個全局變量名,你只需要修改這個全局變量的值,在整個Django中引用它的地方也將同樣獲得改變。這是極為古老、朴素和有用的設計思想,而且這種思想無處不在。

2.4 第一個Django app,Part 2:模型和admin站點

接着上一部分,本節將講述如何安裝數據庫,編寫第一個模型以及簡要的介紹下Django自動生成的admin站點。

2.4.1 數據庫安裝

打開mysite/settings.py配置文件。Django默認使用內置的SQLite數據庫。當然,如果你是在創建一個實際的項目,請使用類似MySql的生產用數據庫,避免以后面臨數據庫切換的頭疼。
如果你想使用別的數據庫,請先安裝相應的數據庫模塊,並將settings文件中DATABASES ’default’的鍵值進行相應的修改,用於連接你的數據庫。其中:

ENGINE(引擎):可以是’django.db.backends.sqlite3’或者’django.db.backends.postgresql’,’django.db.backends.mysql’, or ’django.db.backends.oracle’,當然其它的也行。

NAME(名稱):數據庫的名字。如果你使用的是默認的SQLite,那么數據庫將作為一個文件將存放在你的本地機器內,NAME應該是這個文件的完整絕對路徑,包括文件名。設置中的默認值os.path.join(BASE_DIR, ’db.sqlite3’),將把該文件儲存在你的項目目錄下。

如果你不是使用默認的SQLite數據庫,那么一些諸如USER,PASSWORD和HOST的參數必須手動指定!更多細節參考后續的數據庫章節。

注意:

  • 在使用非SQLite的數據庫時,請務必首先在數據庫提示符交互模式下創建數據庫,你可以使用命令:“CREATE DATABASE database_name;”。
  • 確保你在settings文件中提供的數據庫用戶具有創建數據庫表的權限,因為在接下來的教程中,我們需要自動創建一個test數據庫。
  • 如果你使用的是SQLite,那么你無需做任何預先配置,直接使用就可以了。

在修改settings文件時,請順便將TIME_ZONE設置為你所在的時區。
同時,請注意settings文件中頂部的INSTALLED_APPS設置項。它保存了所有的在當前項目中被激活的Django應用。你必須將你自定義的app注冊在這里。每個應用可以被多個項目使用,而且你可以打包和分發給其他人在他們的項目中使用。

默認情況,INSTALLED_APPS中會自動包含下列條目,它們都是Django自動生成的:

  • django.contrib.admin:admin站點
  • django.contrib.auth:身份認證系統
  • django.contrib.contenttypes:內容類型框架
  • django.contrib.sessions:會話框架
  • django.contrib.messages:消息框架
  • django.contrib.staticfiles:靜態文件管理框架

上面的每個應用都至少需要使用一個數據庫表,所以在使用它們之前我們需要在數據庫中創建這些表。使用這個命令:$ python manage.py migrate。

migrate命令將遍歷INSTALLED_APPS設置中的所有項目,在數據庫中創建對應的表,並打印出每一條動作信息。如果你感興趣,可以在你的數據庫命令行下輸入:\dt (PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 來列出 Django 所創建的表。

提示:對於極簡主義者,你完全可以在INSTALLED_APPS內注釋掉任何或者全部的Django提供的通用應用。這樣,migrate也不會再創建對應的數據表。

2.4.2 創建模型models

Django通過自定義python類的形式來定義具體的模型,每個模型代表數據庫中的一張表,每個類的實例代表數據表中的一行數據,類中的每個變量代表數據表中的一列字段。Django通過ORM對數據庫進行操作,奉行代碼優先的理念,將python程序員和數據庫管理員進行分工解耦。

在這個簡單的投票應用中,我們將創建兩個模型:Question和Choice。Question包含一個問題和一個發布日期。Choice包含兩個字段:選擇的文本和投票計數。每一條Choice都關聯到一條Question。這些都是由python的類來體現,編寫的全是python的代碼,不接觸任何sql語句。現在,編輯polls/models.py文件,具體代碼如下:
polls/models.py

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

上面的代碼非常簡單明了。每一個類都是django.db.models.Model的子類。每一個字段都是Field類的一個實例,例如用於保存字符數據的CharField和用於保存時間類型的DateTimeField,它們告訴Django每一個字段保存的數據類型。

每一個 Field 實例的名字就是字段的名字(如: question_text 或者 pub_date )。在你的Python代碼中會使用這個值,你的數據庫也會將這個值作為表的列名。

你也可以在每個Field中使用一個可選的第一位置參數用於提供一個人類可讀的字段名,讓你的模型更友好,更易讀,並且將被作為文檔的一部分來增強代碼的可讀性。在本例中,僅定義了一個符合人類習慣的字段名Question.pub_date。對於模型中的其他字段,機器名稱就已經足夠我們認讀了。

一些Field類必須提供某些特定的參數。例如CharField需要你指定max_length。這不僅是數據庫結構的需要,同樣也用於我們后面會談到的數據驗證功能。

有必填參數,當然就會有可選參數,比如在votes里我們將其默認值設為0.

最后請注意,我們使用ForeignKey定義了一個外鍵關系。它告訴Django,每一個Choice關聯到一個對應的Question。Django支持通用的數據關系:一對一,多對一和多對多。

2.4.3 激活模型

上面的代碼看着有點少,但卻給予Django大量的信息,據此,Django會做下面兩件事:

  • 創建該app對應的數據庫表結構
  • 為Question和Choice對象創建基於python的數據庫訪問API

但是,首先,我們得先告訴項目,我們已經安裝了投票應用。

Django思想:應用是“可插拔的”:你可以在多個項目使用一個應用,你也可以分發應用,它們不會被捆綁到一個給定的 Django 項目中。

要將應用添加到項目中,需要在INSTALLED_APPS設置中增加指向該應用的配置文件的鏈接。對於本例的投票應用,它的配置類文件是polls/apps.py,路徑格式為’polls.apps.PollsConfig’。我們需要在INSTALLED_APPS中,將該路徑添加進去。它看起來是這樣的:

mysite/settings.py

INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

現在Django已經知道你的投票應用的存在了,並把它加入了大家庭。我們再運行下一個命令:$ python manage.py makemigrations polls。你會看到類似下面的提示:

Migrations for 'polls':
polls/migrations/0001_initial.py:
    - Create model Choice
    - Create model Question
    - Add field question to choice

通過運行migrations命令,相當於告訴Django你對你的模型有改動,並且你想把這些改動保存為一個“遷移”。

migrations是Django保存模型修改記錄的文件,它們是保存在磁盤上的文件。在例子中,它就是polls/migrations/0001_initial.py文件,你可以打開它看看,里面保存的都是可編輯的內容,方便你隨時手動修改。

接下來有一個叫做migrate的命令將對數據庫執行真正的遷移動作,下面我們就要介紹它。但是,在此之前,讓我們先看看在migration的時候實際試行的SQL語句是什么。有一個叫做sqlmigrate的 命令可以展示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的輸出。
  • 表名是自動生成的,通過組合應用名 (polls) 和小寫的模型名 – question 和 choice 。 ( 你可以重寫此行為。)
  • 主鍵 (IDs) 是自動添加的。( 你也可以重寫此行為。)
  • 按照慣例,Django 會在外鍵字段名上附加 "_id" 。 (你仍然可以重寫此行為。)
  • 外鍵關系由FOREIGN KEY顯示聲明。不要擔心DEFERRABLE部分,它只是告訴PostgreSQL不要實施外鍵直到事務結束。
  • 生成 SQL 語句時針對你所使用的數據庫,會為你自動處理特定於數據庫的字段,例如 auto_increment (MySQL), serial (PostgreSQL), 或integer primary key (SQLite) 。 在引用字段名時也是如此 – 比如使用雙引號或單引號。
  • 這些 sql 命令並比較在你的數據庫中實際運行,它只是在屏幕上顯示出來,以便讓你了解 Django 真正執行的是什么。

如果你感興趣,也可以運行python manage.py check命令,它將檢查項目中所有沒有進行遷移或者鏈接數據庫的錯誤。

現在,我們可以運行migrate命令,在數據庫中進行真正的表操作了。

$ python manage.py migrate
Operations to perform:
    Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
    Rendering model states... DONE
    Applying polls.0001_initial... OK

migrate命令對所有還未實施的遷移記錄進行操作,本質上就是將你對模型的修改體現到數據庫中具體的表上面。Django通過一張叫做django_migrations的表,記錄並跟蹤已經實施的migrate動作,通過對比獲得哪些migrations尚未提交。

migrations的功能非常強大,允許你隨時修改你的模型,而不需要刪除或者新建你的數據庫或數據表,在不丟失數據的同時,實時動態更新數據庫。我們將在后面的章節對此進行深入的闡述,但是現在,我們只需要記住修改模型時的操作分三步:

  • 在models.py中修改模型
  • 運行python manage.py makemigrations為改動創建遷移記錄
  • 運行python manage.py migrate,將遷移同步到數據庫,落實修改動作。

之所以要將創建和實施遷移的動作分成兩個命令兩步走是因為你也許要通過版本控制系統(例如github,svn)提交你的項目代碼,如果沒有一個中間過程的保存文件(migrations),那么github如何知道以及記錄、同步、實施你所進行過的模型修改動作呢?畢竟,github不和數據庫直接打交道,也沒法和你本地的數據庫打交道。但是分開之后,你只需要將你的migration文件(例如上面的0001)上傳到github,它就會知道一切。

2.4.4 學會使用API

下面,讓我們進入python交互環境,學習使用Django提供的數據庫訪問API。要進入python的shell,請輸入命令:
$ python manage.py shell

相比較直接輸入“python”命令的方式進入python環境,調用manage.py參數能將DJANGO_SETTINGS_MODULE環境變量導入,它將自動按照mysite/settings.py中的設置,配置好你的python shell環境,這樣,你就可以導入和調用任何你項目內的模塊了。

或者你也可以這樣,先進入一個純凈的python shell環境,然后啟動Django,具體如下:

>>> import django
>>> django.setup()

如果上述操作出現AttributeError異常,有可能是你正在使用一個和當前教程不匹配的Django版本。解決辦法是學習較低版本的教程或更換更新版本的Django。

不管是哪種方式,你最終都是讓python命令能夠找到正確的模塊地址,得到正確的導入。

當你進入shell后,嘗試一下下面的API吧:

    >>> from polls.models import Question, Choice # 導入我們寫的模型類
    # 現在系統內還沒有questions
    >>> Question.objects.all()
    <QuerySet []>
    
    # 創建一個新的question
    # Django推薦使用timezone.now()代替python內置的datetime.datetime.now()
    from django.utils import timezone
    >>> q = Question(question_text="What's new?", pub_date=timezone.now())
    
    # 你必須顯式的調用save()方法,才能將對象保存到數據庫內
    >>> q.save()
    
    # 默認情況,你會自動獲得一個自增的名為id的主鍵
    >>> 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()
    
    # objects.all() 用於查詢數據庫內的所有questions
    >>> Question.objects.all()
    <QuerySet [<Question: Question object>]>

這里等一下:上面的<Question: Question object>是一個不可讀的內容展示,你無法從中獲得任何直觀的信息,為此我們需要一點小技巧,讓Django在打印對象時顯示一些我們指定的信息。返回polls/models.py文件,修改一下question和Choice這兩個類,代碼如下:

polls/models.py

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible # 當你想支持python2版本的時候才需要這個裝飾器
class Question(models.Model):
    # ...
    def __str__(self):   # 在python2版本中使用的是__unique__
        return self.question_text
        
@python_2_unicode_compatible 
class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

這個技巧不但對你打印對象時很有幫助,在你使用Django的admin站點時也同樣有幫助。

請注意,這些都是普通的Python方法。下面我們自定義一個方法,作為示范:

polls/models.py

import datetime
from django.db import models
from django.utils import timezone

class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

請注意上面分別導入了兩個關於時間的模塊,一個是python內置的datetime一個是Django工具包提供的timezone。

保存修改后,我們重新啟動一個新的python shell,再來看看其他的API:

>>> from polls.models import Question, Choice

# 先看看__str__()的效果,直觀多了吧?
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django提供了大量的關鍵字參數查詢API
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# 獲取今年發布的問卷
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# 查詢一個不存在的ID,會彈出異常
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.

# Django為主鍵查詢提供了一個縮寫:pk。下面的語句和Question.objects.get(id=1)效果一樣.
>>> Question.objects.get(pk=1)
<Question: What's up?>

# 看看我們自定義的方法用起來怎么樣
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# 讓我們試試主鍵查詢
>>> q = Question.objects.get(pk=1)

# 顯示所有與q對象有關系的choice集合,目前是空的,還沒有任何關聯對象。
>>> q.choice_set.all()
<QuerySet []>

# 創建3個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對象可通過API訪問和他們關聯的Question對象
>>> c.question
<Question: What's up?>

# 同樣的,Question對象也可通過API訪問關聯的Choice對象
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# API會自動進行連表操作,通過雙下划線分割關系對象。連表操作可以無限多級,一層一層的連接。
# 下面是查詢所有的Choices,它所對應的Question的發布日期是今年。(重用了上面的current_year結果)
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# 使用delete方法刪除對象
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

獲取更多關於模型關系的信息,請查看6.15.4章節。更多的數據庫API和如何使用雙下划線進行查詢,請看3.2.2章節。

2.4.5 Django admin站點介紹

設計理念:為你的團隊或客戶編寫用於增加、修改和刪除內容的admin站點是一件非常乏味的工作並且沒有多少創造性。因此,Django自動地為你通過模型構造了一個admin站點。這個站點只給站點管理員使用,並不對大眾開放。

  • 創建管理員用戶

首先,通過下面的命令,創建一個可以登錄admin站點的用戶:
$ python manage.py createsuperuser
輸入用戶名:
Username: admin
輸入郵箱地址:
Email address: admin@example.com
輸入密碼:
Password: **********
Password (again): *********
Superuser created successfully.

注意:Django1.10版本后,超級用戶的密碼強制要求具備一定的復雜性,不能再偷懶了。

  • 啟動開發服務器

服務器啟動后,在瀏覽器訪問http://127.0.0.1:8000/admin/。你就能看到admin的登陸界面了:

  • 進入admin站點

利用剛才建立的admin賬戶,登陸站點,你將看到如下的界面:

當前已經有兩個可編輯的內容:groups和users。它們是django.contrib.auth模塊提供的身份認證框架。

  • 在admin中注冊你的投票應用

現在你還無法看到你的投票應用,必須先在admin中進行注冊,告訴admin站點,請將poll的模型加入站點內,接受站點的管理。

打開polls/admin.py文件,加入下面的內容:

polls/admin.py

from django.contrib import admin
from .models import Question

admin.site.register(Question)
  • 瀏覽admin站點的功能

注冊question模型后,刷新admin頁面就能看到Question欄目了。

點擊“Questions”,進入questions的修改列表頁面。這個頁面會顯示所有的數據庫內的questions對象,你可以在這里對它們進行修改。看到下面的“What’s up?”了么?它就是我們先前創建的一個question,並且通過__str__方法的幫助,顯示了較為直觀的信息,而不是一個冷冰冰的對象類型名稱。

下面,點擊What’s up?進入編輯界面:

這里需要注意的是:

  • 表單是由Question模型自動生成的
  • 不同的模型字段類型(DateTimeField, CharField)會表現為不同的HTML input框類型。
  • 每一個DateTimeField都會獲得一個JS縮寫。日期的縮寫是Today,並有一個日歷彈出框;時間的縮寫是Now,並有一個通用的時間輸入列表框。

在頁面的底部,則是一些可選項按鈕:

  • delete:彈出一個刪除確認頁面
  • save and add another:保存當前修改,並加載一個新的空白的當前類型對象的表單。
  • save and continue editing:保存當前修改,並重新加載該對象的編輯頁面。
  • save:保存修改,返回當前對象類型的列表頁面。

如果“Date published”字段的值和你在前面教程創建它的時候不一致,可能是你沒有正確的配置TIME_ZONE,在國內,通常是8個小時的時間差別。修改TIME_ZONE配置並重新加載頁面,就能顯示正確的時間了。

在頁面的右上角,點擊“History”按鈕,你會看到你對當前對象的所有修改操作都在這里有記錄,包括修改時間和操作人,如下圖所示:

到此,你對模型API和admin站點有了一定的熟悉,可以進入下一階段的教程了。

覺得還行就點贊支持一下吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM