1. 程式人生 > >python之django

python之django

歡迎學習django課程

MVC

  • 大部分開發語言中都有MVC框架
  • MVC框架的核心思想是:解耦
  • 降低各功能模組之間的耦合性,方便變更,更容易重構程式碼,最大程度上實現程式碼的重用
  • m表示model,主要用於對資料庫層的封裝
  • v表示view,用於向用戶展示結果
  • c表示controller,是核心,用於處理請求、獲取資料、返回結果

MVT

  • Django是一款python的web開發框架
  • 與MVC有所不同,屬於MVT框架
  • m表示model,負責與資料庫互動
  • v表示view,是核心,負責接收請求、獲取資料、返回結果
  • t表示template,負責呈現內容到瀏覽器

簡介

  • 通過簡單示例,使用django完成基本流程的開發,學習django的主要的知識點,在後續課程中會逐個知識點進行深入講解
  • 以“圖書-英雄”管理為示例

主要知識點介紹

  • 環境搭建
  • 定義模型
  • 使用後臺管理
  • 編寫檢視
  • 定義模板

建立虛擬環境

  • 建立:mkvirtualenv [虛擬環境名稱]
  • 刪除:rmvirtualenv [虛擬環境名稱]
  • 進入:workon [虛擬環境名稱]
  • 退出:deactivate
  • 所有的虛擬環境,都位於/home/.virtualenvs目錄下
  • 進入虛擬環境前的提示:
  • 進入虛擬環境後的提示:

  • 檢視當前的所有虛擬環境:workon [兩次tab鍵]
  • 檢視虛擬環境中已經安裝的包
pip list
pip freeze

安裝django

  • 建議安裝1.8.2版本,這是一個穩定性高、使用廣、文件多的版本
pip install django==1.8.2
  • 檢視版本:進入python shell,執行如下程式碼
import django
django.get_version()
  • 說明:使用pip install django命令進行安裝時,會自動刪除舊版本,再安裝新版本

建立專案

  • 命令django-admin startproject test1
  • 進入test1目錄,目錄結構如下圖:

目錄說明

  • manage.py:一個命令列工具,可以使你用多種方式對Django專案進行互動
  • 內層的目錄:專案的真正的Python包
  • _init _.py:一個空檔案,它告訴Python這個目錄應該被看做一個Python包
  • settings.py:專案的配置
  • urls.py:專案的URL宣告
  • wsgi.py:專案與WSGI相容的Web伺服器入口

設計介紹

  • 本示例完成“圖書-英雄”資訊的維護,需要儲存兩種資料:圖書、英雄
  • 圖書表結構設計:
    • 表名:BookInfo
    • 圖書名稱:btitle
    • 圖書釋出時間:bpub_date
  • 英雄表結構設計:
    • 表名:HeroInfo
    • 英雄姓名:hname
    • 英雄性別:hgender
    • 英雄簡介:hcontent
    • 所屬圖書:hbook
  • 圖書-英雄的關係為一對多

資料庫配置

  • 在settings.py檔案中,通過DATABASES項進行資料庫設定
  • django支援的資料庫包括:sqlite、mysql等主流資料庫
  • Django預設使用SQLite資料庫

建立應用

在一個專案中可以建立一到多個應用,每個應用進行一種業務處理 建立應用的命令:

python manage.py startapp booktest
  • 應用的目錄結構如下圖

定義模型類

  • 有一個數據表,就有一個模型類與之對應
  • 開啟models.py檔案,定義模型類
  • 引入包from django.db import models
  • 模型類繼承自models.Model類
  • 說明:不需要定義主鍵列,在生成時會自動新增,並且值為自動增長
  • 當輸出物件時,會呼叫物件的str方法
from django.db import models

class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateTimeField()
    def _ _str_ _(self):
        return "%d" % self.pk

class HeroInfo(models.Model):
    hname = models.CharField(max_length=20)
    hgender = models.BooleanField()
    hcontent = models.CharField(max_length=100)
    hBook = models.ForeignKey('BookInfo')
    def _ _str_ _(self):
        return "%d" % self.pk

生成資料表

  • 啟用模型:編輯settings.py檔案,將booktest應用加入到installed_apps中

 

  • 生成遷移檔案:根據模型類生成sql語句
python manage.py makemigrations
  • 遷移檔案被生成到應用的migrations目錄

 

  • 執行遷移:執行sql語句生成資料表
python manage.py migrate

測試資料操作

  • 進入python shell,進行簡單的模型API練習
python manage.py shell
  • 進入shell後提示如下:

 

  • 引入需要的包:
from booktest.models import BookInfo,HeroInfo
from django.utils import timezone
from datetime import *
  • 查詢所有圖書資訊:
BookInfo.objects.all()
  • 新建圖書資訊:
b = BookInfo()
b.btitle="射鵰英雄傳"
b.bpub_date=datetime(year=1990,month=1,day=10)
b.save()
  • 查詢圖書資訊:
b=BookInfo.objects.get(pk=1)
  • 輸出圖書資訊:
b
b.id
b.btitle
  • 修改圖書資訊:
b.btitle=u"天龍八部"
b.save()
  • 刪除圖書資訊:
b.delete()

關聯物件的操作

  • 對於HeroInfo可以按照上面的操作方式進行
  • 新增,注意新增關聯物件
h=HeroInfo()
h.htitle=u'郭靖'
h.hgender=True
h.hcontent=u'降龍十八掌'
h.hBook=b
h.save()
  • 獲得關聯集合:返回當前book物件的所有hero
b.heroinfo_set.all()
  • 有一個HeroInfo存在,必須要有一個BookInfo物件,提供了建立關聯的資料:
h=b.heroinfo_set.create(htitle=u'黃蓉',hgender=False,hcontent=u'打狗棍法')
h

伺服器

  • 執行如下命令可以開啟伺服器
python manage.py runserver ip:port
  • 可以不寫ip,預設埠為8000
  • 這是一個純python編寫的輕量級web伺服器,僅在開發階段使用
  • 伺服器成功啟動後,提示如下資訊

 

  • 預設埠是8000,可以修改埠
python manage.py runserver 8080
  • 開啟瀏覽器,輸入網址“127.0.0.1:8000”可以開啟預設頁面
  • 如果修改檔案不需要重啟伺服器,如果增刪檔案需要重啟伺服器
  • 通過ctrl+c停止伺服器

管理操作

  • 站點分為“內容釋出”和“公共訪問”兩部分
  • “內容釋出”的部分負責新增、修改、刪除內容,開發這些重複的功能是一件單調乏味、缺乏創造力的工作。為此,Django會根據定義的模型類完全自動地生成管理模組

使用django的管理

  • 建立一個管理員使用者
python manage.py createsuperuser,按提示輸入使用者名稱、郵箱、密碼
  • 啟動伺服器,通過“127.0.0.1:8000/admin”訪問,輸入上面建立的使用者名稱、密碼完成登入
  • 進入管理站點,預設可以對groups、users進行管理

管理介面本地化

  • 編輯settings.py檔案,設定編碼、時區
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

向admin註冊booktest的模型

  • 開啟booktest/admin.py檔案,註冊模型
from django.contrib import admin
from models import BookInfo
admin.site.register(BookInfo)
  • 重新整理管理頁面,可以對BookInfo的資料進行增刪改查操作
  • 問題:如果在str方法中返回中文,在修改和新增時會報ascii的錯誤
  • 解決:在str()方法中,將字串末尾新增“.encode('utf-8')”

自定義管理頁面

  • Django提供了admin.ModelAdmin類
  • 通過定義ModelAdmin的子類,來定義模型在Admin介面的顯示方式
class QuestionAdmin(admin.ModelAdmin):
    ...
admin.site.register(Question, QuestionAdmin)

列表頁屬性

  • list_display:顯示欄位,可以點選列頭進行排序
list_display = ['pk', 'btitle', 'bpub_date']
  • list_filter:過濾欄位,過濾框會出現在右側
list_filter = ['btitle']
  • search_fields:搜尋欄位,搜尋框會出現在上側
search_fields = ['btitle']
  • list_per_page:分頁,分頁框會出現在下側
list_per_page = 10

新增、修改頁屬性

  • fields:屬性的先後順序
fields = ['bpub_date', 'btitle']
  • fieldsets:屬性分組
fieldsets = [
    ('basic',{'fields': ['btitle']}),
    ('more', {'fields': ['bpub_date']}),
]

關聯物件

  • 對於HeroInfo模型類,有兩種註冊方式

    • 方式一:與BookInfo模型類相同
    • 方式二:關聯註冊
  • 按照BookInfor的註冊方式完成HeroInfo的註冊

  • 接下來實現關聯註冊
from django.contrib import admin
from models import BookInfo,HeroInfo

class HeroInfoInline(admin.StackedInline):
    model = HeroInfo
    extra = 2

class BookInfoAdmin(admin.ModelAdmin):
    inlines = [HeroInfoInline]

admin.site.register(BookInfo, BookInfoAdmin)
  • 可以將內嵌的方式改為表格
class HeroInfoInline(admin.TabularInline)

布林值的顯示

  • 釋出性別的顯示不是一個直觀的結果,可以使用方法進行封裝
def gender(self):
    if self.hgender:
        return '男'
    else:
        return '女'
gender.short_description = '性別'
  • 在admin註冊中使用gender代替hgender
class HeroInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'hname', 'gender', 'hcontent']

檢視

  • 在django中,檢視對WEB請求進行迴應
  • 檢視接收reqeust物件作為第一個引數,包含了請求的資訊
  • 檢視就是一個Python函式,被定義在views.py中
#coding:utf-8
from django.http import HttpResponse

def index(request):
    return HttpResponse("index")
def detail(request,id):
    return HttpResponse("detail %s" % id)
  • 定義完成檢視後,需要配置urlconf,否則無法處理請求

URLconf

  • 在Django中,定義URLconf包括正則表示式、檢視兩部分
  • Django使用正則表示式匹配請求的URL,一旦匹配成功,則呼叫應用的檢視
  • 注意:只匹配路徑部分,即除去域名、引數後的字串
  • 在test1/urls.py插入booktest,使主urlconf連線到booktest.urls模組
url(r'^', include('booktest.urls')),
  • 在booktest中的urls.py中新增urlconf
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index),
    url(r'^([0-9]+)/$', views.detail),
]

模板

  • 模板是html頁面,可以根據檢視中傳遞的資料填充值
  • 建立模板的目錄如下圖:

 

  • 修改settings.py檔案,設定TEMPLATES的DIRS值
'DIRS': [os.path.join(BASE_DIR, 'templates')],
  • 在模板中訪問檢視傳遞的資料
{{輸出值,可以是變數,也可以是物件.屬性}}
{%執行程式碼段%}

定義index.html模板

<!DOCTYPE html>
<html>
<head>
  <title>首頁</title>
</head>
<body>
<h1>圖書列表</h1>
<ul>
{%for book in booklist%}
<li>
  <a href="{{book.id}}">
    {{book.btitle}}
  </a>
</li>
{%endfor%}
</ul>
</body>
</html>

定義detail.html模板

  • 在模板中訪問物件成員時,都以屬性的方式訪問,即方法也不能加括號
<!DOCTYPE html>
<html>
<head>
  <title>詳細頁</title>
</head>
<body>
<h1>{{book.btitle}}</h1>
<ul>
  {%for hero in book.heroinfo_set.all%}
  <li>{{hero.hname}}---{{hero.hcontent}}</li>
  {%endfor%}
</ul>
</body>
</html>

使用模板

  • 編輯views.py檔案,在方法中呼叫模板
from django.http import HttpResponse
from django.template import RequestContext, loader
from models import BookInfo

def index(request):
    booklist = BookInfo.objects.all()
    template = loader.get_template('booktest/index.html')
    context = RequestContext(request, {'booklist': booklist})
    return HttpResponse(template.render(context))


def detail(reqeust, id):
    book = BookInfo.objects.get(pk=id)
    template = loader.get_template('booktest/detail.html')
    context = RequestContext(reqeust, {'book': book})
    return HttpResponse(template.render(context))

去除模板的硬編碼

  • 在index.html模板中,超連結是硬編碼的,此時的請求地址為“127.0.0.1/1/”
<a href="{{book.id}}">
  • 看如下情況:將urlconf中詳細頁改為如下,連結就找不到了
url(r'^book/([0-9]+)/$', views.detail),
  • 此時的請求地址應該為“127.0.0.1/book/1/”
  • 問題總結:如果在模板中地址硬編碼,將來urlconf修改後,地址將失效
  • 解決:使用命名的url設定超連結
  • 修改test1/urls.py檔案,在include中設定namespace
url(r'^admin/', include(admin.site.urls, namespace='booktest')),
  • 修改booktest/urls.py檔案,設定name
url(r'^book/([0-9]+)/$', views.detail, name="detail"),
  • 修改index.html模板中的連結
<a href="{%url 'booktest:detail' book.id%}">

Render簡寫

  • Django提供了函式Render()簡化檢視呼叫模板、構造上下文
from django.shortcuts import render
from models import BookInfo

def index(reqeust):
    booklist = BookInfo.objects.all()
    return render(reqeust, 'booktest/index.html', {'booklist': booklist})


def detail(reqeust, id):
    book = BookInfo.objects.get(pk=id)
    return render(reqeust, 'booktest/detail.html', {'book': book})

總結

  1. 安裝配置django執行的環境
  2. 編寫模型,使用簡單API與資料庫互動
  3. 使用django的後臺管理中維護資料
  4. 通過檢視接收請求,通過模型獲取資料,展示出來
  5. 呼叫模板完成展示

作業

  • 設計一對多關係的兩個模型類
  • 使用django後臺管理
  • 通過檢視、urlconf、模板完成資料的展示
  • 控制在2個小時之內完成

ORM簡介

  • MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫
  • ORM是“物件-關係-對映”的簡稱,主要任務是:
    • 根據物件的型別生成表結構
    • 將物件、列表的操作,轉換為sql語句
    • 將sql查詢到的結果轉換為物件、列表
  • 這極大的減輕了開發人員的工作量,不需要面對因資料庫變更而導致的無效勞動
  • Django中的模型包含儲存資料的欄位和約束,對應著資料庫中唯一的表

 

使用MySql資料庫

  • 在虛擬環境中安裝mysql包
pip install mysql-python
  • 在mysql中建立資料庫
create databases test2 charset=utf8
  • 開啟settings.py檔案,修改DATABASES項
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2',
        'USER': '使用者名稱',
        'PASSWORD': '密碼',
        'HOST': '資料庫伺服器ip,本地可以使用localhost',
        'PORT': '埠,預設為3306',
    }
}

開發流程

  1. 在models.py中定義模型類,要求繼承自models.Model
  2. 把應用加入settings.py檔案的installed_app項
  3. 生成遷移檔案
  4. 執行遷移生成表
  5. 使用模型類進行crud操作

使用資料庫生成模型類

python manage.py inspectdb > booktest/models.py

定義模型

  • 在模型中定義屬性,會生成表中的欄位
  • django根據屬性的型別確定以下資訊:
    • 當前選擇的資料庫支援欄位的型別
    • 渲染管理表單時使用的預設html控制元件
    • 在管理站點最低限度的驗證
  • django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設定某屬性為主鍵列後,則django不會再生成預設的主鍵列
  • 屬性命名限制
    • 不能是python的保留關鍵字
    • 由於django的查詢方式,不允許使用連續的下劃線

定義屬性

  • 定義屬性時,需要欄位型別
  • 欄位型別被定義在django.db.models.fields目錄下,為了方便使用,被匯入到django.db.models中
  • 使用方式
    1. 匯入from django.db import models
    2. 通過models.Field建立欄位型別的物件,賦值給屬性
  • 對於重要資料都做邏輯刪除,不做物理刪除,實現方法是定義isDelete屬性,型別為BooleanField,預設值為False

欄位型別

  • AutoField:一個根據實際ID自動增長的IntegerField,通常不指定
    • 如果不指定,一個主鍵欄位將自動新增到模型中
  • BooleanField:true/false 欄位,此欄位的預設表單控制是CheckboxInput
  • NullBooleanField:支援null、true、false三種值
  • CharField(max_length=字元長度):字串,預設的表單樣式是 TextInput
  • TextField:大文字欄位,一般超過4000使用,預設的表單控制元件是Textarea
  • IntegerField:整數
  • DecimalField(max_digits=None, decimal_places=None):使用python的Decimal例項表示的十進位制浮點數
    • DecimalField.max_digits:位數總數
    • DecimalField.decimal_places:小數點後的數字位數
  • FloatField:用Python的float例項來表示的浮點數
  • DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date例項表示的日期
    • 引數DateField.auto_now:每次儲存物件時,自動設定該欄位為當前時間,用於"最後一次修改"的時間戳,它總是使用當前日期,預設為false
    • 引數DateField.auto_now_add:當物件第一次被建立時自動設定當前時間,用於建立的時間戳,它總是使用當前日期,預設為false
    • 該欄位預設對應的表單控制元件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日曆控制元件,和一個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤訊息鍵
    • auto_now_add, auto_now, and default 這些設定是相互排斥的,他們之間的任何組合將會發生錯誤的結果
  • TimeField:使用Python的datetime.time例項表示的時間,引數同DateField
  • DateTimeField:使用Python的datetime.datetime例項表示的日期和時間,引數同DateField
  • FileField:一個上傳檔案的欄位
  • ImageField:繼承了FileField的所有屬性和方法,但對上傳的物件進行校驗,確保它是個有效的image

欄位選項

  • 通過欄位選項,可以實現對欄位的約束
  • 在欄位物件時通過關鍵字引數指定
  • null:如果為True,Django 將空值以NULL 儲存到資料庫中,預設值是 False
  • blank:如果為True,則該欄位允許為空白,預設值是 False
  • 對比:null是資料庫範疇的概念,blank是表單驗證證範疇的
  • db_column:欄位的名稱,如果未指定,則使用屬性的名稱
  • db_index:若值為 True, 則在表中會為此欄位建立索引
  • default:預設值
  • primary_key:若為 True, 則該欄位會成為模型的主鍵欄位
  • unique:如果為 True, 這個欄位在表中必須有唯一值

關係

  • 關係的型別包括
    • ForeignKey:一對多,將欄位定義在多的端中
    • ManyToManyField:多對多,將欄位定義在兩端中
    • OneToOneField:一對一,將欄位定義在任意一端中
  • 可以維護遞迴的關聯關係,使用'self'指定,詳見“自關聯”
  • 用一訪問多:物件.模型類小寫_set
bookinfo.heroinfo_set
  • 用一訪問一:物件.模型類小寫
heroinfo.bookinfo
  • 訪問id:物件.屬性_id
heroinfo.book_id

元選項

  • 在模型類中定義類Meta,用於設定元資訊
  • 元資訊db_table:定義資料表名稱,推薦使用小寫字母,資料表的預設名稱
<app_name>_<model_name>
  • ordering:物件的預設排序欄位,獲取物件的列表時使用,接收屬性構成的列表
class BookInfo(models.Model):
    ...
    class Meta():
        ordering = ['id']
  • 字串前加-表示倒序,不加-表示正序
class BookInfo(models.Model):
    ...
    class Meta():
        ordering = ['-id']
  • 排序會增加資料庫的開銷

示例演示

  • 建立test2專案,並建立booktest應用,使用mysql資料庫
  • 定義圖書模型
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateTimeField()
    bread = models.IntegerField(default=0)
    bcommet = models.IntegerField(default=0)
    isDelete = models.BooleanField(default=False)
  • 英雄模型
class HeroInfo(models.Model):
    hname = models.CharField(max_length=20)
    hgender = models.BooleanField(default=True)
    isDelete = models.BooleanField(default=False)
    hcontent = models.CharField(max_length=100)
    hbook = models.ForeignKey('BookInfo')
  • 定義index、detail檢視
  • index.html、detail.html模板
  • 配置url,能夠完成圖書及英雄的展示

測試資料

  • 模型BookInfo的測試資料
insert into booktest_bookinfo(btitle,bpub_date,bread,bcommet,isDelete) values
('射鵰英雄傳','1980-5-1',12,34,0),
('天龍八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飛狐','1987-11-11',58,24,0)
  • 模型HeroInfo的測試資料
insert into booktest_heroinfo(hname,hgender,hbook_id,hcontent,isDelete) values
('郭靖',1,1,'降龍十八掌',0),
('黃蓉',0,1,'打狗棍法',0),
('黃藥師',1,1,'彈指神通',0),
('歐陽鋒',1,1,'蛤蟆功',0),
('梅超風',0,1,'九陰白骨爪',0),
('喬峰',1,2,'降龍十八掌',0),
('段譽',1,2,'六脈神劍',0),
('虛竹',1,2,'天山六陽掌',0),
('王語嫣',0,2,'神仙姐姐',0),
('令狐沖',1,3,'獨孤九劍',0),
('任盈盈',0,3,'彈琴',0),
('嶽不群',1,3,'華山劍法',0),
('東方不敗',0,3,'葵花寶典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若蘭',0,4,'黃衣',0),
('程靈素',0,4,'醫術',0),
('袁紫衣',0,4,'六合拳',0)

類的屬性

  • objects:是Manager型別的物件,用於與資料庫進行互動
  • 當定義模型類時沒有指定管理器,則Django會為模型類提供一個名為objects的管理器
  • 支援明確指定模型類的管理器
class BookInfo(models.Model):
    ...
    books = models.Manager()
  • 當為模型類指定管理器後,django不再為模型類生成名為objects的預設管理器

管理器Manager

  • 管理器是Django的模型進行資料庫的查詢操作的介面,Django應用的每個模型都擁有至少一個管理器
  • 自定義管理器類主要用於兩種情況
  • 情況一:向管理器類中新增額外的方法:見下面“建立物件”中的方式二
  • 情況二:修改管理器返回的原始查詢集:重寫get_queryset()方法
class BookInfoManager(models.Manager):
    def get_queryset(self):
        return super(BookInfoManager, self).get_queryset().filter(isDelete=False)
class BookInfo(models.Model):
    ...
    books = BookInfoManager()

建立物件

  • 當建立物件時,django不會對資料庫進行讀寫操作
  • 呼叫save()方法才與資料庫互動,將物件儲存到資料庫中
  • 使用關鍵字引數構造模型物件很麻煩,推薦使用下面的兩種之式
  • 說明: _init _方法已經在基類models.Model中使用,在自定義模型中無法使用,
  • 方式一:在模型類中增加一個類方法
class BookInfo(models.Model):
    ...
    @classmethod
    def create(cls, title, pub_date):
        book = cls(btitle=title, bpub_date=pub_date)
        book.bread=0
        book.bcommet=0
        book.isDelete = False
        return book
引入時間包:from datetime import *
呼叫:book=BookInfo.create("hello",datetime(1980,10,11));
儲存:book.save()
  • 方式二:在自定義管理器中新增一個方法
  • 在管理器的方法中,可以通過self.model來得到它所屬的模型類
class BookInfoManager(models.Manager):
    def create_book(self, title, pub_date):
        book = self.model()
        book.btitle = title
        book.bpub_date = pub_date
        book.bread=0
        book.bcommet=0
        book.isDelete = False
        return book

class BookInfo(models.Model):
    ...
    books = BookInfoManager()
呼叫:book=BookInfo.books.create_book("abc",datetime(1980,1,1))
儲存:book.save()
  • 在方式二中,可以呼叫self.create()建立並儲存物件,不需要再手動save()
class BookInfoManager(models.Manager):
    def create_book(self, title, pub_date):
        book = self.create(btitle = title,bpub_date = pub_date,bread=0,bcommet=0,isDelete = False)
        return book

class BookInfo(models.Model):
    ...
    books = BookInfoManager()
呼叫:book=Book.books.create_book("abc",datetime(1980,1,1))
檢視:book.pk

例項的屬性

  • DoesNotExist:在進行單個查詢時,模型的物件不存在時會引發此異常,結合try/except使用

例項的方法

  • str (self):重寫object方法,此方法在將物件轉換成字串時會被呼叫
  • save():將模型物件儲存到資料表中
  • delete():將模型物件從資料表中刪除

簡介

  • 查詢集表示從資料庫中獲取的物件集合
  • 查詢集可以含有零個、一個或多個過濾器
  • 過濾器基於所給的引數限制查詢的結果
  • 從Sql的角度,查詢集和select語句等價,過濾器像where和limit子句
  • 接下來主要討論如下知識點
    • 查詢集
    • 欄位查詢:比較運算子,F物件,Q物件

查詢集

  • 在管理器上呼叫過濾器方法會返回查詢集
  • 查詢集經過過濾器篩選後返回新的查詢集,因此可以寫成鏈式過濾
  • 惰性執行:建立查詢集不會帶來任何資料庫的訪問,直到呼叫資料時,才會訪問資料庫
  • 何時對查詢集求值:迭代,序列化,與if合用
  • 返回查詢集的方法,稱為過濾器
    • all()
    • filter()
    • exclude()
    • order_by()
    • values():一個物件構成一個字典,然後構成一個列表返回
  • 寫法:
filter(鍵1=值1,鍵2=值2)
等價於
filter(鍵1=值1).filter(鍵2=值2)
  • 返回單個值的方法
    • get():返回單個滿足條件的物件
      • 如果未找到會引發"模型類.DoesNotExist"異常
      • 如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常
    • count():返回當前查詢的總條數
    • first():返回第一個物件
    • last():返回最後一個物件
    • exists():判斷查詢集中是否有資料,如果有則返回True

限制查詢集

  • 查詢集返回列表,可以使用下標的方式進行限制,等同於sql中的limit和offset子句
  • 注意:不支援負數索引
  • 使用下標後返回一個新的查詢集,不會立即執行查詢
  • 如果獲取一個物件,直接使用[0],等同於[0:1].get(),但是如果沒有資料,[0]引發IndexError異常,[0:1].get()引發DoesNotExist異常

查詢集的快取

  • 每個查詢集都包含一個快取來最小化對資料庫的訪問
  • 在新建的查詢集中,快取為空,首次對查詢集求值時,會發生資料庫查詢,django會將查詢的結果存在查詢集的快取中,並返回請求的結果,接下來對查詢集求值將重用快取的結果
  • 情況一:這構成了兩個查詢集,無法重用快取,每次查詢都會與資料庫進行一次互動,增加了資料庫的負載
print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])
  • 情況二:兩次迴圈使用同一個查詢集,第二次使用快取中的資料
querylist=Entry.objects.all()
print([e.title for e in querylist])
print([e.title for e in querylist])
  • 何時查詢集不會被快取:當只對查詢集的部分進行求值時會檢查快取,但是如果這部分不在快取中,那麼接下來查詢返回的記錄將不會被快取,這意味著使用索引來限制查詢集將不會填充快取,如果這部分資料已經被快取,則直接使用快取中的資料

欄位查詢

  • 實現where子名,作為方法filter()、exclude()、get()的引數
  • 語法:屬性名稱__比較運算子=值
  • 表示兩個下劃線,左側是屬性名稱,右側是比較型別
  • 對於外來鍵,使用“屬性名_id”表示外來鍵的原始值
  • 轉義:like語句中使用了%與,匹配資料中的%與,在過濾器中直接寫,例如:filter(title__contains="%")=>where title like '%\%%',表示查詢標題中包含%的

比較運算子

  • exact:表示判等,大小寫敏感;如果沒有寫“比較運算子”,表示判等
filter(isDelete=False)
  • contains:是否包含,大小寫敏感
exclude(btitle__contains='傳')
  • startswith、endswith:以value開頭或結尾,大小寫敏感
exclude(btitle__endswith='傳')
  • isnull、isnotnull:是否為null
filter(btitle__isnull=False)
  • 在前面加個i表示不區分大小寫,如iexact、icontains、istarswith、iendswith
  • in:是否包含在範圍內
filter(pk__in=[1, 2, 3, 4, 5])
  • gt、gte、lt、lte:大於、大於等於、小於、小於等於
filter(id__gt=3)
  • year、month、day、week_day、hour、minute、second:對日期間型別的屬性進行運算
filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))
  • 跨關聯關係的查詢:處理join查詢
    • 語法:模型類名<屬性名><比較>
    • 注:可以沒有__<比較>部分,表示等於,結果同inner join
    • 可返向使用,即在關聯的兩個模型中都可以使用
filter(heroinfo_ _hcontent_ _contains='八')
  • 查詢的快捷方式:pk,pk表示primary key,預設的主鍵是id
filter(pk__lt=6)

聚合函式

  • 使用aggregate()函式返回聚合函式的值
  • 函式:Avg,Count,Max,Min,Sum
from django.db.models import Max
maxDate = list.aggregate(Max('bpub_date'))
  • count的一般用法:
count = list.count()

F物件

  • 可以使用模型的欄位A與欄位B進行比較,如果A寫在了等號的左邊,則B出現在等號的右邊,需要通過F物件構造
list.filter(bread__gte=F('bcommet'))
  • django支援對F()物件使用算數運算
list.filter(bread__gte=F('bcommet') * 2)
  • F()物件中還可以寫作“模型類__列名”進行關聯查詢
list.filter(isDelete=F('heroinfo__isDelete'))
  • 對於date/time欄位,可與timedelta()進行運算
list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

Q物件

  • 過濾器的方法中關鍵字引數查詢,會合併為And進行
  • 需要進行or查詢,使用Q()物件
  • Q物件(django.db.models.Q)用於封裝一組關鍵字引數,這些關鍵字引數與“比較運算子”中的相同
from django.db.models import Q
list.filter(Q(pk_ _lt=6))
  • Q物件可以使用&(and)、|(or)操作符組合起來
  • 當操作符應用在兩個Q物件時,會產生一個新的Q物件
list.filter(pk_ _lt=6).filter(bcommet_ _gt=10)
list.filter(Q(pk_ _lt=6) | Q(bcommet_ _gt=10))
  • 使用~(not)操作符在Q物件前表示取反
list.filter(~Q(pk__lt=6))
  • 可以使用&|~結合括號進行分組,構造做生意複雜的Q物件
  • 過濾器函式可以傳遞一個或多個Q物件作為位置引數,如果有多個Q物件,這些引數的邏輯為and
  • 過濾器函式可以混合使用Q物件和關鍵字引數,所有引數都將and在一起,Q物件必須位於關鍵字引數的前面

自連線

  • 對於地區資訊,屬於一對多關係,使用一張表,儲存所有的資訊
  • 類似的表結構還應用於分類資訊,可以實現無限級分類
  • 新建模型AreaInfo,生成遷移
class AreaInfo(models.Model):
    atitle = models.CharField(max_length=20)
    aParent = models.ForeignKey('self', null=True, blank=True)
  • 訪問關聯物件
上級物件:area.aParent
下級物件:area.areainfo_set.all()
  • 加入測試資料(在workbench中,參見“省市區mysql.txt”)
  • 在booktest/views.py中定義檢視area
from models import AreaInfo
def area(request):
    area = AreaInfo.objects.get(pk=130100)
    return render(request, 'booktest/area.html', {'area': area})
  • 定義模板area.html
<!DOCTYPE html>
<html>
<head>
    <title>地區</title>
</head>
<body>
當前地區:{{area.atitle}}
<hr/>
上級地區:{{area.aParent.atitle}}
<hr/>
下級地區:
<ul>
    { %for a in area.areainfo_set.all%}
    <li>{{a.atitle}}</li>
    { %endfor%}
</ul>
</body>
</html>
  • 在booktest/urls.py中配置一個新的urlconf
urlpatterns = [
    url(r'^area/$', views.area, name='area')
]

總結

  • 使用mysql資料庫
  • 定義模型,生成遷移
  • 定義管理器
  • 查詢
  • 自連線

作業

  • 熟練完成當天程式碼
  • 上次作業中定義的模型,改為使用mysql資料庫操作
  • 對模型資料進行查詢

檢視

  • 檢視接受Web請求並且返回Web響應
  • 檢視就是一個python函式,被定義在views.py中
  • 響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤等等
  • 響應處理過程如下圖:

 

URLconf

  • 在settings.py檔案中通過ROOT_URLCONF指定根級url的配置
  • urlpatterns是一個url()例項的列表
  • 一個url()物件包括:
    • 正則表示式
    • 檢視函式
    • 名稱name
  • 編寫URLconf的注意:
    • 若要從url中捕獲一個值,需要在它周圍設定一對圓括號
    • 不需要新增一個前導的反斜槓,如應該寫作'test/',而不應該寫作'/test/'
    • 每個正則表示式前面的r表示字串不轉義
  • 請求的url被看做是一個普通的python字串,進行匹配時不包括get或post請求的引數及域名
http://www.itcast.cn/python/1/?i=1&p=new,只匹配“/python/1/”部分
  • 正則表示式非命名組,通過位置引數傳遞給檢視
url(r'^([0-9]+)/$', views.detail, name='detail'),
  • 正則表示式命名組,通過關鍵字引數傳遞給檢視,本例中關鍵字引數為id
url(r'^(?P<id>[0-9]+)/$', views.detail, name='detail'),
  • 引數匹配規則:優先使用命名引數,如果沒有命名引數則使用位置引數
  • 每個捕獲的引數都作為一個普通的python字串傳遞給檢視
  • 效能:urlpatterns中的每個正則表示式在第一次訪問它們時被編譯,這使得系統相當快

包含其它的URLconfs

  • 在應用中建立urls.py檔案,定義本應用中的urlconf,再在專案的settings中使用include()
from django.conf.urls import include, url
urlpatterns = [
    url(r'^', include('booktest.urls', namespace='booktest')),
]
  • 匹配過程:先與主URLconf匹配,成功後再用剩餘的部分與應用中的URLconf匹配
請求http://www.itcast.cn/booktest/1/
在sesstings.py中的配置:
url(r'^booktest/', include('booktest.urls', namespace='booktest')),
在booktest應用urls.py中的配置
url(r'^([0-9]+)/$', views.detail, name='detail'),
匹配部分是:/booktest/1/
匹配過程:在settings.py中與“booktest/”成功,再用“1/”與booktest應用的urls匹配
  • 使用include可以去除urlconf的冗餘
  • 引數:檢視會收到來自父URLconf、當前URLconf捕獲的所有引數
  • 在include中通過namespace定義名稱空間,用於反解析

URL的反向解析

  • 如果在檢視、模板中使用硬編碼的連結,在urlconf發生改變時,維護是一件非常麻煩的事情
  • 解決:在做連結時,通過指向urlconf的名稱,動態生成連結地址
  • 檢視:使用django.core.urlresolvers.reverse()函式
  • 模板:使用url模板標籤

定義檢視

  • 本質就是一個函式
  • 檢視的引數
    • 一個HttpRequest例項
    • 通過正則表示式組獲取的位置引數
    • 通過正則表示式組獲得的關鍵字引數
  • 在應用目錄下預設有views.py檔案,一般檢視都定義在這個檔案中
  • 如果處理功能過多,可以將函式定義到不同的py檔案中
新建views1.py
#coding:utf-8
from django.http import HttpResponse
def index(request):
    return HttpResponse("你好")

在urls.py中修改配置
from . import views1
url(r'^$', views1.index, name='index'),

錯誤檢視

  • Django原生自帶幾個預設檢視用於處理HTTP錯誤

404 (page not found) 檢視

  • defaults.page_not_found(request, template_name='404.html')
  • 預設的404檢視將傳遞一個變數給模板:request_path,它是導致錯誤的URL
  • 如果Django在檢測URLconf中的每個正則表示式後沒有找到匹配的內容也將呼叫404檢視
  • 如果在settings中DEBUG設定為True,那麼將永遠不會呼叫404檢視,而是顯示URLconf 並帶有一些除錯資訊
  • 在templates中建立404.html
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
找不到了
<hr/>
{{request_path}}
</body>
</html>
  • 在settings.py中修改除錯
DEBUG = False
ALLOWED_HOSTS = ['*', ]
  • 請求一個不存在的地址
http://127.0.0.1:8000/test/

500 (server error) 檢視

  • defaults.server_error(request, template_name='500.html')
  • 在檢視程式碼中出現執行時錯誤
  • 預設的500檢視不會傳遞變數給500.html模板
  • 如果在settings中DEBUG設定為True,那麼將永遠不會呼叫505檢視,而是顯示URLconf 並帶有一些除錯資訊

400 (bad request) 檢視

  • defaults.bad_request(request, template_name='400.html')
  • 錯誤來自客戶端的操作
  • 當用戶進行的操作在安全方面可疑的時候,例如篡改會話cookie

HttpReqeust物件

  • 伺服器接收到http協議的請求後,會根據報文建立HttpRequest物件
  • 檢視函式的第一個引數是HttpRequest物件
  • 在django.http模組中定義了HttpRequest物件的API

屬性

  • 下面除非特別說明,屬性都是隻讀的
  • path:一個字串,表示請求的頁面的完整路徑,不包含域名
  • method:一個字串,表示請求使用的HTTP方法,常用值包括:'GET'、'POST'
  • encoding:一個字串,表示提交的資料的編碼方式
    • 如果為None則表示使用瀏覽器的預設設定,一般為utf-8
    • 這個屬性是可寫的,可以通過修改它來修改訪問表單資料使用的編碼,接下來對屬性的任何訪問將使用新的encoding值
  • GET:一個類似於字典的物件,包含get請求方式的所有引數
  • POST:一個類似於字典的物件,包含post請求方式的所有引數
  • FILES:一個類似於字典的物件,包含所有的上傳檔案
  • COOKIES:一個標準的Python字典,包含所有的cookie,鍵和值都為字串
  • session:一個既可讀又可寫的類似於字典的物件,表示當前的會話,只有當Django 啟用會話的支援時才可用,詳細內容見“狀態保持”

方法

  • is_ajax():如果請求是通過XMLHttpRequest發起的,則返回True

QueryDict物件

  • 定義在django.http.QueryDict
  • request物件的屬性GET、POST都是QueryDict型別的物件
  • 與python字典不同,QueryDict型別的物件用來處理同一個鍵帶有多個值的情況
  • 方法get():根據鍵獲取值
    • 只能獲取鍵的一個值
    • 如果一個鍵同時擁有多個值,獲取最後一個值
dict.get('鍵',default)
或簡寫為
dict['鍵']
  • 方法getlist():根據鍵獲取值
    • 將鍵的值以列表返回,可以獲取一個鍵的多個值
dict.getlist('鍵',default)

GET屬性

  • QueryDict型別的物件
  • 包含get請求方式的所有引數
  • 與url請求地址中的引數對應,位於?後面
  • 引數的格式是鍵值對,如key1=value1
  • 多個引數之間,使用&連線,如key1=value1&key2=value2
  • 鍵是開發人員定下來的,值是可變的
  • 示例如下
  • 建立檢視getTest1用於定義連結,getTest2用於接收一鍵一值,getTest3用於接收一鍵多值
def getTest1(request):
    return render(request,'booktest/getTest1.html')
def getTest2(request):
    return render(request,'booktest/getTest2.html')
def getTest3(request):
    return render(request,'booktest/getTest3.html')
  • 配置url
url(r'^getTest1/$', views.getTest1),
url(r'^getTest2/$', views.getTest2),
url(r'^getTest3/$', views.getTest3),
  • 建立getTest1.html,定義連結
<html>
<head>
    <title>Title</title>
</head>
<body>
連結1:一個鍵傳遞一個值
<a href="/getTest2/?a=1&b=2">gettest2</a><br>
連結2:一個鍵傳遞多個值
<a href="/getTest3/?a=1&a=2&b=3">gettest3</a>
</body>
</html>
  • 完善檢視getTest2的程式碼
def getTest2(request):
    a=request.GET['a']
    b=request.GET['b']
    context={'a':a,'b':b}
    return render(request,'booktest/getTest2.html',context)
  • 建立getTest2.html,顯示接收結果
<html>
<head>
    <title>Title</title>
</head>
<body>
a:{{ a }}<br>
b:{{ b }}
</body>
</html>
  • 完善檢視getTest3的程式碼
def getTest3(request):
    a=request.GET.getlist('a')
    b=request.GET['b']
    context={'a':a,'b':b}
    return render(request,'booktest/getTest3.html',context)
  • 建立getTest3.html,顯示接收結果
<html>
<head>
    <title>Title</title>
</head>
<body>
a:{% for item in a %}
{{ item }}
{% endfor %}
<br>
b:{{ b }}
</body>
</html>

POST屬性

  • QueryDict型別的物件
  • 包含post請求方式的所有引數
  • 與form表單中的控制元件對應
  • 問:表單中哪些控制元件會被提交?
  • 答:控制元件要有name屬性,則name屬性的值為鍵,value屬性的值為鍵,構成鍵值對提交
    • 對於checkbox控制元件,name屬性一樣為一組,當控制元件被選中後會被提交,存在一鍵多值的情況
  • 鍵是開發人員定下來的,值是可變的
  • 示例如下
  • 定義檢視postTest1
def postTest1(request):
    return render(request,'booktest/postTest1.html')
  • 配置url
url(r'^postTest1$',views.postTest1)
  • 建立模板postTest1.html
<html>
<head>
    <title>Title</title>
</head>
<body>
<form method="post" action="/postTest2/">
    姓名:<input type="text" name="uname"/><br>
    密碼:<input type="password" name="upwd"/><br>
    性別:<input type="radio" name="ugender" value="1"/>男
    <input type="radio" name="ugender" value="0"/>女<br>
    愛好:<input type="checkbox" name="uhobby" value="胸口碎大石"/>胸口碎大石
    <input type="checkbox" name="uhobby" value="跳樓"/>跳樓
    <input type="checkbox" name="uhobby" value="喝酒"/>喝酒
    <input type="checkbox" name="uhobby" value="爬山"/>爬山<br>
    <input type="submit" value="提交"/>
</form>
</body>
</html>
  • 建立檢視postTest2接收請求的資料
def postTest2(request):
    uname=request.POST['uname']
    upwd=request.POST['upwd']
    ugender=request.POST['ugender']
    uhobby=request.POST.getlist('uhobby')
    context={'uname':uname,'upwd':upwd,'ugender':ugender,'uhobby':uhobby}
    return render(request,'booktest/postTest2.html',context)
  • 配置url
url(r'^postTest2$',views.postTest2)
  • 建立模板postTest2.html
<html>
<head>
    <title>Title</title>
</head>
<body>
{{ uname }}<br>
{{ upwd }}<br>
{{ ugender }}<br>
{{ uhobby }}
</body>
</html>
  • 注意:使用表單提交,註釋掉settings.py中的中介軟體crsf

HttpResponse物件

  • 在django.http模組中定義了HttpResponse物件的API
  • HttpRequest物件由Django自動建立,HttpResponse物件由程式設計師建立
  • 不呼叫模板,直接返回資料
#coding=utf-8
from django.http import HttpResponse

def index(request):
    return HttpResponse('你好')
  • 呼叫模板
from django.http import HttpResponse
from django.template import RequestContext, loader

def index(request):
    t1 = loader.get_template('polls/index.html')
    context = RequestContext(request, {'h1': 'hello'})
    return HttpResponse(t1.render(context))

屬性

  • content:表示返回的內容,字串型別
  • charset:表示response採用的編碼字符集,字串型別
  • status_code:響應的HTTP響應狀態碼
  • content-type:指定輸出的MIME型別

方法

  • init :使用頁內容例項化HttpResponse物件
  • write(content):以檔案的方式寫
  • flush():以檔案的方式輸出快取區
  • set_cookie(key, value='', max_age=None, expires=None):設定Cookie
    • key、value都是字串型別
    • max_age是一個整數,表示在指定秒數後過期
    • expires是一個datetime或timedelta物件,會話將在這個指定的日期/時間過期,注意datetime和timedelta值只有在使用PickleSerializer時才可序列化
    • max_age與expires二選一
    • 如果不指定過期時間,則兩個星期後過期
from django.http import HttpResponse
from datetime import *

def index(request):
    response = HttpResponse()
    if request.COOKIES.has_key('h1'):
        response.write('<h1>' + request.COOKIES['h1'] + '</h1>')
    response.set_cookie('h1', '你好', 120)
    # response.set_cookie('h1', '你好', None, datetime(2016, 10, 31))
    return response
  • delete_cookie(key):刪除指定的key的Cookie,如果key不存在則什麼也不發生

子類HttpResponseRedirect

  • 重定向,伺服器端跳轉
  • 建構函式的第一個引數用來指定重定向的地址
在views1.py中
from django.http import HttpResponse,HttpResponseRedirect
def index(request):
    return HttpResponseRedirect('js/')
def index2(request,id):
    return HttpResponse(id)

在應用的urls.py中增加一個url物件
url(r'^([0-9]+)/$', views1.index2, name='index2'),
  • 請求位址列如圖:

請求位址列

  • 請求結果的位址列如圖:

請求位址列

  • 推薦使用反向解析
from django.core.urlresolvers import reverse

def index(request):
    return HttpResponseRedirect(reverse('booktest:index2', args=(1,)))

子類JsonResponse

  • 返回json資料,一般用於非同步請求
  • _init _(data)
  • 幫助使用者建立JSON編碼的響應
  • 引數data是字典物件
  • JsonResponse的預設Content-Type為application/json
from django.http import JsonResponse

def index2(requeset):
    return JsonResponse({'list': 'abc'})

簡寫函式

render

  • render(request, template_name[, context])
  • 結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的HttpResponse物件
  • request:該request用於生成response
  • template_name:要使用的模板的完整名稱
  • context:新增到模板上下文的一個字典,檢視將在渲染模板之前呼叫它
from django.shortcuts import render

def index(request):
    return render(request, 'booktest/index.html', {'h1': 'hello'})

重定向

  • redirect(to)
  • 為傳遞進來的引數返回HttpResponseRedirect
  • to推薦使用反向解析
from django.shortcuts import redirect
from django.core.urlresolvers import reverse

def index(request):
    return redirect(reverse('booktest:index2'))

得到物件或返回404

  • get_object_or_404(klass, args, *kwargs)
  • 通過模型管理器或查詢集呼叫get()方法,如果沒找到物件,不引發模型的DoesNotExist異常,而是引發Http404異常
  • klass:獲取物件的模型類、Manager物件或QuerySet物件
  • **kwargs:查詢的引數,格式應該可以被get()和filter()接受
  • 如果找到多個物件將引發MultipleObjectsReturned異常
from django.shortcuts import *

def detail(request, id):
    try:
        book = get_object_or_404(BookInfo, pk=id)
    except BookInfo.MultipleObjectsReturned:
        book = None
    return render(request, 'booktest/detail.html', {'book': book})

將settings.py中的DEBUG改為False
將請求地址輸入2和100檢視效果

得到列表或返回404

  • get_list_or_404(klass, args, *kwargs)
  • klass:獲取列表的一個Model、Manager或QuerySet例項
  • **kwargs:查尋的引數,格式應該可以被get()和filter()接受
from django.shortcuts import *

def index(request):
    # list = get_list_or_404(BookInfo, pk__lt=1)
    list = get_list_or_404(BookInfo, pk__lt=6)
    return render(request, 'booktest/index.html', {'list': list})

將settings.py中的DEBUG改為False

狀態保持

  • http協議是無狀態的:每次請求都是一次新的請求,不會記得之前通訊的狀態
  • 客戶端與伺服器端的一次通訊,就是一次會話
  • 實現狀態保持的方式:在客戶端或伺服器端儲存與會話有關的資料
  • 儲存方式包括cookie、session,會話一般指session物件
  • 使用cookie,所有資料儲存在客戶端,注意不要儲存敏感資訊
  • 推薦使用sesison方式,所有資料儲存在伺服器端,在客戶端cookie中儲存session_id
  • 狀態保持的目的是在一段時間內跟蹤請求者的狀態,可以實現跨頁面訪問當前請求者的資料
  • 注意:不同的請求者之間不會共享這個資料,與請求者一一對應

啟用session

  • 使用django-admin startproject建立的專案預設啟用
  • 在settings.py檔案中
項INSTALLED_APPS列表中新增:
'django.contrib.sessions',

項MIDDLEWARE_CLASSES列表中新增:
'django.contrib.sessions.middleware.SessionMiddleware',
  • 禁用會話:刪除上面指定的兩個值,禁用會話將節省一些效能消耗

使用session

  • 啟用會話後,每個HttpRequest物件將具有一個session屬性,它是一個類字典物件
  • get(key, default=None):根據鍵獲取會話的值
  • clear():清除所有會話
  • flush():刪除當前的會話資料並刪除會話的Cookie
  • del request.session['member_id']:刪除會話

使用者登入示例

  • 操作效果如下圖:

 

 

  • 在views.py檔案中建立檢視
from django.shortcuts import render, redirect
from django.core.urlresolvers import reverse

def index(request):
    uname = request.session.get('uname')
    return render(request, 'booktest/index.html', {'uname': uname})

def login(request):
    return render(request, 'booktest/login.html')

def login_handle(request):
    request.session['uname'] = request.POST['uname']
    return redirect(reverse('main:index'))

def logout(