Django框架簡介
Django是Python最有代表性的一個網絡框架。使用Django可以方便地實現一個功能全面、管理簡便的網站或者APP後端。openstack中用來提供圖形化界面服務的Dashboard就是利用Django框架進行開發,所以在介紹openstack dashboard開發之前,通過本篇文章針對Django應用開發進行講解。
Django的MTV(模型-模板-視圖)模式本質上和一般MVC(模型-視圖-控制器)是一樣的。其中M代表模型(Model),負責業務對象和數據庫關係的映射,即ORM;T代表模板(Template),負責如何把頁面展示給用戶,即HTML;V代表視圖,負責業務邏輯,並在適當時候調用Model和Template。除了以上三層之外,還需要一個URL分發器、它的作用是將一個個URL的頁面請求,分發給不同的視圖處理,視圖再調用相應的數據模型和模板。MTV的響應模式如下圖所示:
1,Web服務器(中間件)收到一個http請求
2,Django在URLconf裏查找對應的視圖(View)函數來處理http請求
3,視圖函數調用相應的數據模型來存取數據、調用相應的模板向用戶展示頁面
4,視圖函數處理結束後返回一個http的響應給Web服務器
5,Web服務器將響應發送給客戶端
這種設計模式關鍵的優勢在於各種組件都是鬆耦合的。這樣,每個由 Django驅動的Web應用都有着明確的目的,並且可獨立更改而不影響到其它的部分。
比如,開發者更改一個應用程序中的 URL 而不用影響到這個程序底層的實現。設計師可以改變 HTML頁面的樣式而不用接觸Python代碼。
數據庫管理員可以重新命名數據表並且只需更改模型,無需從一大堆文件中進行查找和替換。
Django的MTV模式相對應的python文件如下:
Django簡單應用開發
爲了能夠更好地理解Django框架原理,我們通過Django開發一個簡單的web應用,來熟悉基於Django框架的web應用開發流程。該應用可以在客戶端進行靜態頁面展示,也可以在客戶端通過在網頁上提交表單的方法,修改服務器中數據庫的數據,並在網頁上可以查詢數據庫中的數據。其開發流程如下所示:
創建Django項目
通過devstack部署好all-in-one的openstack環境之後,Django也相應安裝完成,可以在想要創建Django項目文件夾的目錄下執行如下命令,創建Django項目,這裏我們設置Django的項目名爲mysite
django-admin.py startproject mysite
此時生成的mysite項目文件夾如下所示:
創建第一個頁面
下面通過創建一個簡單的靜態展示頁面來了解URLs分發和處理HTTP請求,首先需要將URL對應分配給某個對象處理,這需要在mysite/mysite下的urls.py設定。Python會根據該程序,將URL請求分給某個對象。urls.py的內容修改如下:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$','mysite.views.first_page'),
]
其中最後一行的作用是將根目錄的URL分配給一個對象進行處理,這個對象爲mysite/mysite下views.py中的first_page函數,目前views.py文件夾還不存在,需要我們自己創建並定義first_page函數,py文件內容如下:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
def first_page(request):
return HttpResponse("<p>第一個頁面</p>")
此時便可以啓動服務器查看該靜態頁面,在mysite目錄下使用如下命令啓動服務器:
./manage.py runserver 8080
此時通過訪問127.0.0.1:8080端口即可看到如下頁面:
增加一個app
一個網站可能有多個功能。可以在Django下,以app爲單位實現模塊化管理,而不是將所有的東西都放到一個文件夾下。在mysite下運行manage.py,創建新的名爲app_test的app:
python manage.py startapp app_test
該命令執行後,會在mysite目錄下生成app_test目錄,目錄文件結構如下所示:
要使用app_test,需要在mysite/setting.py的INSTALLED_APPS原組中增加app_test:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app_test',
)
我們可以爲該app增加一個靜態首頁。之前在mysite/urls.py中設置的URL訪問對象依然採用類似的方式設置。另一方面,實現模塊化,應該在app_test/urls.py中設置URL訪問對象。首先修改mysite/urls.py中的內容:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$','mysite.views.first_page'),
url(r'^app_test/', include('app_test.urls')),
]
通過最後一行來訪問app_test,而對於app_test/下的訪問,則在app_test/urls.py中設置:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',url(r'^$','app_test.views.first_page'),)
將URL對應到app_test下的views.py中的first_page函數(參考上面的first_page),
通過啓動服務器後訪問http://127.0.0.1:8080/app_test即可訪問該靜態頁面
使用數據庫
Django爲多種數據庫後臺提供了統一的調用API。根據需求不同,Django可以選擇不同的數據庫後臺。這裏將Django和MySQL連接。
首先在MySQL中創立Django項目的數據庫,爲Django項目創建用戶並授予相關權限,該用戶用戶名爲test,密碼爲test:
CREATE DATABASE django DEFAULT CHARSET=utf8;
GRANT ALL PRIVILEGES ON django.* TO 'test'@'localhost' IDENTIFIED BY 'test'
在mysite/setting.py中設置DATABASE對象如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER': 'test',
'PASSWORD': 'test',
'HOST': 'localhost',
'PORT': '3306',
}
}
Django根據setting中的設置,即可使用test用戶在數據庫中讀寫。MySQL作爲關係型數據庫,在Django的幫助下,可以不用直接編寫SQL語句。Django可以直接將關係型表(table)轉換成一個類(class),而每個記錄(record)是該類下的一個對象(object),這樣便可以使用基於對象的方法來操縱關係型數據庫MySQL。在傳統的MySQL中,數據模型是表;在Django下,一個表爲一個類,表的每一列都是該類的一個屬性。此次我們創建一個只有一列的表,即只有一個屬性的類,通過在app_test/models.py中添加該類:
from django.db import models
# Create your models here.
class Character(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return self.name
該表只有一列,即name。
models.py修改完成之後,通過如下命令在MySQL中真正創建各個關係表
python manage.py syncdb
python manage.py makemigrations
此時通過test用戶進入MySQL的Django庫中即可看到表名爲app_test_character的表。我們在表中手動添加如下三條記錄:
INSERT INTO app_test_character (name) Values ("xiao ming");
INSERT INTO app_test_character (name) Values ("xiao zhang");
INSERT INTO app_test_character (name) Values ("xiao Fang");
下面通過代碼從數據庫中取出數據,並返回給HTTP請求。在app_test/views.py中添加視圖函數all(),從數據庫中讀取所有記錄然後返回客戶端:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from app_test.models import Character
def all(request):
all_list = Character.objects.all()
all_str = map(str,all_list)
return HttpResponse("<p>"+' '.join(all_str)+"</p>")
可以看到,從app_test.models中引入Character類。通過操作該類,我們可以讀取表中的記錄。爲了能讓http請求能夠找到上面的數據,在app_test/urls.py中增加URL導航:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',url(r'^$','app_test.views.first_page'),url(r'^all/','app_test.views.all'),)
運行服務器。在瀏覽器中輸入URL:127.0.0.1:8080/app_test/all/,可以在網頁上查看到該三條記錄
通過提交表單(POST)方法在頁面提交併存儲數據
在前面的內容中,我們採用手動的方式,直接在數據庫中插入數據。這裏將介紹通過提交表單(POST)方法來向後端服務器中的數據庫提交數據。我們採用POST方法,並用一個URL和處理函數,同時顯示視圖和處理請求。我們在app_test/views.py中創建處理函數investigate()。該函數可以通過Django提供的數據對象,對用戶提交的數據進行檢驗和處理之後存入數據庫的表中:
from django.http import HttpResponse
from app_test.models import Character
from django.shortcuts import render
from django.core.context_processors import csrf
from django import forms
class CharacterForm(forms.Form):
name = forms.CharField(max_length = 200)
def investigate(request):
if request.POST:
form = CharacterForm(request.POST)
if form.is_valid():
submitted = form.cleaned_data['name']
new_record = Character(name = submitted)
new_record.save()
form = CharacterForm()
ctx = {}
ctx.update(csrf(request))
all_records = Character.objects.all()
ctx['templay'] = all_records
ctx['form'] = form
return render(request,"app_test/investigate.html",ctx)
上面程序定義了CharacterForm類,並通過屬性name,說明了輸入欄name的類型爲字符串,最大長度爲200.而在investigate函數中,根據request的POST內容直接創立了form對象。該對象可以直接判斷輸入是否有效,並對輸入進行預處理。空白輸入被視爲無效。最後一行return使用render方法來代替之前使用的HttpResponse,ctx字典作爲模板app_test/investigate.html的參數,該模板文件位於mysite/templates/app_test/文件夾下(需要在根目錄mysite下新建templates文件夾),內容如下所示:
<form action="/app_test/investigate/" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
{% for person in templay %}
<p>{{ person }}</p>
{% endfor %}
最後在app_test/urls.py中增加URL導航:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',url(r'^$','app_test.views.first_page'),
url(r'^all/','app_test.views.all'),
url(r'^investigate/','app_test.views.investigate'),)
運行服務器,輸入http://127.0.0.1:8080/app_test/investigate,會顯示如下內容,通過提交查詢可以將數據輸入並顯示錶中所有內容