Python之Django框架的使用
1、安裝Django
pip install django
2、建立Django專案
django-admin startproject 專案名稱
3、在setting檔案中配置資料庫
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '',
'USER':'root',
'PASSWORD':'',
'HOST':'',
'PORT':'',
}
}
4、建立應用
python manage.py startapp 應用名稱
5、定義模型類models.py,一個類對應資料庫的一個表,一個屬性,對應資料表中的一個欄位
from django.db import models
class 類名(models.Model):
xxxx=models.CharField(max_length=20)
。。。
6、生成資料表
- 啟用模型:編輯settings.py檔案,將應用加入到installed_apps中
- 生成遷移檔案:根據模型類生成sql語句
python manage.py makemigrations
- 執行遷移:執行sql語句生成資料表
python manage.py migrate
7、執行Django專案,預設埠8000
python manage.py runserver ip:port
8、使用Django的管理
- 建立一個管理員使用者
python manage.py createsuperuser,按提示輸入使用者名稱、郵箱、密碼
- 啟動伺服器,通過“127.0.0.1:8000/admin”訪問,輸入上面建立的使用者名稱、密碼完成登入
- 進入管理站點,預設可以對groups、users進行管理
9、管理介面本地化
- 編輯settings.py檔案,設定編碼、時區
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
10、向admin註冊應用的模型
-
開啟admin.py檔案,註冊模型
from django.contrib import admin
from models import xxx
admin.site.register(xxx)
11、檢視
- 在django中,檢視對WEB請求進行迴應
- 檢視接收reqeust物件作為第一個引數,包含了請求的資訊
- 檢視就是一個Python函式,被定義在views.py中
#coding:utf-8
from django.http import HttpResponse
def index(request):
return HttpResponse("index")
- 定義完成檢視後,需要配置urlconf,否則無法處理請求
12、模板
- 模板是html頁面,可以根據檢視中傳遞的資料填充值
- 修改settings.py檔案,設定TEMPLATES的DIRS值
'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 在模板中訪問檢視傳遞的資料
{{輸出值,可以是變數,也可以是物件.屬性}}
{%執行程式碼段%}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
{{xxx}}
</body>
</html>
13、使用模板
- 編輯views.py檔案,在方法中呼叫模板
from django.http import HttpResponse
from django.template import RequestContext, loader
from models import xxx
def index(request):
booklist = BookInfo.objects.all()
template = loader.get_template('xxx.html')
context = RequestContext(request, {'xxx': xxx})
return HttpResponse(template.render(context))
def detail(reqeust, id):
xxx = BookInfo.objects.get(pk=id)
template = loader.get_template(xxx.html')
context = RequestContext(reqeust, {'xxx': xxx})
return HttpResponse(template.render(context))
14、Render
- Django提供了函式Render()簡化檢視呼叫模板、構造上下文
from django.shortcuts import render
from models import xxx
def index(reqeust):
xxx = xxx.objects.all()
return render(reqeust, 'xxxx.html', {'xxx': xxx})
def detail(reqeust, id):
xxx = xxx.objects.get(pk=id)
return render(reqeust, 'xxx.html', {'xxx': xxx})
15、ORM簡介
- MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫
- ORM是“物件-關係-對映”的簡稱,主要任務是:
- 根據物件的型別生成表結構
- 將物件、列表的操作,轉換為sql語句
- 將sql查詢到的結果轉換為物件、列表
- 這極大的減輕了開發人員的工作量,不需要面對因資料庫變更而導致的無效勞動
- Django中的模型包含儲存資料的欄位和約束,對應著資料庫中唯一的表 16、使用MySql資料庫
- 安裝mysql包
pip install mysql-python
- 在mysql中建立資料庫
create databases 資料庫名字 charset=utf8
- 開啟settings.py檔案,修改DATABASES項
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': '使用者名稱',
'PASSWORD': '密碼',
'HOST': '資料庫伺服器ip,本地可以使用localhost',
'PORT': '埠,預設為3306',
}
}
17、開發流程
- 在models.py中定義模型類,要求繼承自models.Model
- 把應用加入settings.py檔案的installed_app項
- 生成遷移檔案
- 執行遷移生成表
- 使用模型類進行crud操作
18、使用資料庫生成模型類
python manage.py inspectdb > xxx/models.py
19、定義模型
- 在模型中定義屬性,會生成表中的欄位
- django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設定某屬性為主鍵列後,則django不會再生成預設的主鍵列
- 屬性命名限制 & 不能是python的保留關鍵字 & 由於django的查詢方式,不允許使用連續的下劃線
20、定義屬性 對於重要資料都做邏輯刪除,不做物理刪除,實現方法是定義isDelete屬性,型別為BooleanField,預設值為False
21、元選項
- 在模型類中定義類Meta,用於設定元資訊
- 元資訊db_table:定義資料表名稱,推薦使用小寫字母,資料表的預設名稱
- ordering:物件的預設排序欄位,獲取物件的列表時使用,接收屬性構成的列表
class BookInfo(models.Model):
...
class Meta():
ordering = ['id']
- 字串前加-表示倒序,不加-表示正序
class BookInfo(models.Model):
...
class Meta():
ordering = ['-id']
- 排序會增加資料庫的開銷
22、管理器Manager
- 用於與資料庫進行互動
- 當定義模型類時沒有指定管理器,則Django會為模型類提供一個名為objects的管理器
- 支援明確指定模型類的管理器
- 當為模型類指定管理器後,django不再為模型類生成名為objects的預設管理器
- 管理器是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()
23 、建立物件
- 說明: _init _方法已經在基類models.Model中使用,在自定義模型中無法使用,
- 方式一:在模型類中增加一個類方法
class BookInfo(models.Model):
...
@classmethod
def create(cls, title, pub_date):
book = cls(btitle=title, bpub_date=pub_date)
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.isDelete = False
return book
class BookInfo(models.Model):
...
books = BookInfoManager()
呼叫:book=BookInfo.books.create_book("abc",datetime(1980,1,1))
儲存:book.save()
24、例項的屬性
- DoesNotExist:在進行單個查詢時,模型的物件不存在時會引發此異常,結合try/except使用
25、例項的方法
- str (self):重寫object方法,此方法在將物件轉換成字串時會被呼叫
- save():將模型物件儲存到資料表中
- delete():將模型物件從資料表中刪除
26、查詢集
- 在管理器上呼叫過濾器方法會返回查詢集
- 查詢集經過過濾器篩選後返回新的查詢集,因此可以寫成鏈式過濾
- 惰性執行:建立查詢集不會帶來任何資料庫的訪問,直到呼叫資料時,才會訪問資料庫
- 何時對查詢集求值:迭代,序列化,與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
26、限制查詢集
- 查詢集返回列表,可以使用下標的方式進行限制,等同於sql中的limit和offset子句
- 注意:不支援負數索引
- 使用下標後返回一個新的查詢集,不會立即執行查詢
- 如果獲取一個物件,直接使用[0],等同於[0:1].get(),但是如果沒有資料,[0]引發IndexError異常,[0:1].get()引發DoesNotExist異常
27、查詢集的快取
- 每個查詢集都包含一個快取來最小化對資料庫的訪問
- 在新建的查詢集中,快取為空,首次對查詢集求值時,會發生資料庫查詢,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])
- 何時查詢集不會被快取:當只對查詢集的部分進行求值時會檢查快取,但是如果這部分不在快取中,那麼接下來查詢返回的記錄將不會被快取,這意味著使用索引來限制查詢集將不會填充快取,如果這部分資料已經被快取,則直接使用快取中的資料
28、欄位查詢
- 實現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物件必須位於關鍵字引數的前面
29、錯誤檢視
- 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 = ['*', ]
30、HttpReqeust物件
-
is_ajax():如果請求是通過XMLHttpRequest發起的,則返回True
-
31、QueryDict物件
-
定義在django.http.QueryDict
-
request物件的屬性GET、POST都是QueryDict型別的物件
-
與python字典不同,QueryDict型別的物件用來處理同一個鍵帶有多個值的情況
-
方法get():根據鍵獲取值 – 只能獲取鍵的一個值
-
如果一個鍵同時擁有多個值,獲取最後一個值
dict.get('鍵',default)
或簡寫為
dict['鍵']
-
方法getlist():根據鍵獲取值 – 將鍵的值以列表返回,可以獲取一個鍵的多個值 – dict.getlist(‘鍵’,default)
31、HttpResponse物件
- 在django.http模組中定義了HttpResponse物件的API
- HttpRequest物件由Django自動建立,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))
32、HttpResponseRedirect
- 重定向,伺服器端跳轉
- 建構函式的第一個引數用來指定重定向的地址
33、JsonResponse
- 返回json資料,一般用於非同步請求
- _init _(data)
- 幫助使用者建立JSON編碼的響應
- 引數data是字典物件
- sonResponse的預設Content-Type為application/json
from django.http import JsonResponse
def index2(requeset):
return JsonResponse({'list': 'abc'})
34、啟用session
- 使用django-admin startproject建立的專案預設啟用
- 在settings.py檔案中
項INSTALLED_APPS列表中新增:
'django.contrib.sessions',
項MIDDLEWARE_CLASSES列表中新增:
'django.contrib.sessions.middleware.SessionMiddleware',
- 禁用會話:刪除上面指定的兩個值,禁用會話將節省一些效能消耗
- 啟用會話後,每個HttpRequest物件將具有一個session屬性,它是一個類字典物件
- get(key, default=None):根據鍵獲取會話的值
- clear():清除所有會話
- flush():刪除當前的會話資料並刪除會話的Cookie
- del request.session[‘member_id’]:刪除會話
35、會話過期時間
- set_expiry(value):設定會話的超時時間
- 如果沒有指定,則兩個星期後過期
- 如果value是一個整數,會話將在values秒沒有活動後過期
- 若果value是一個imedelta物件,會話將在當前時間加上這個指定的日期/時間過期
- 如果value為0,那麼使用者會話的Cookie將在使用者的瀏覽器關閉時過期
- 如果value為None,那麼會話永不過期
- 修改檢視中login_handle函式,檢視效果 儲存session
- 使用儲存會話的方式,可以使用settings.py的SESSION_ENGINE項指定
- 基於資料庫的會話:這是django預設的會話儲存方式,需要新增django.contrib.sessions到的INSTALLED_APPS設定中,執行manage.py migrate在資料庫中安裝會話表,可顯示指定為
SESSION_ENGINE='django.contrib.sessions.backends.db'
- 基於快取的會話:只存在本地內在中,如果丟失則不能找回,比資料庫的方式讀寫更快
SESSION_ENGINE='django.contrib.sessions.backends.cache'
- 可以將快取和資料庫同時使用:優先從本地快取中獲取,如果沒有則從資料庫中獲取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
使用Redis快取session
- 會話還支援檔案、純cookie、Memcached、Redis等方式儲存,下面演示使用redis儲存
- 安裝包
pip install django-redis-sessions
- 修改settings中的配置,增加如下項
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'
- 管理redis的命令
啟動:sudo redis-server /etc/redis/redis.conf
停止:sudo redis-server stop
重啟:sudo redis-server restart
redis-cli:使用客戶端連線伺服器
keys *:檢視所有的鍵
get name:獲取指定鍵的值
del name:刪除指定名稱的鍵
36、模板
- 定義模板路徑
DIRS=[os.path.join(BASE_DIR,"templates")]
- 模板處理
-
- Django處理模板分為兩個階段
-
- Step1 載入:根據給定的標識找到模板然後預處理,通常會將它編譯好放在記憶體中
loader.get_template(template_name),返回一個Template物件
- Step2 渲染:使用Context資料對模板插值並返回生成的字串
Template物件的render(RequestContext)方法,使用context渲染模板
- 載入渲染完整程式碼:
from django.template import loader, RequestContext
from django.http import HttpResponse
def index(request):
tem = loader.get_template('temtest/index.html')
context = RequestContext(request, {})
return HttpResponse(tem.render(context))
快捷函式
- 為了減少載入模板、渲染模板的重複程式碼,django提供了快捷函式
- render_to_string("")
- render(request,‘模板’,context)
from django.shortcuts import render
def index(request):
return render(request, 'temtest/index.html')
- csrf_token:這個標籤用於跨站請求偽造保護
{ % csrf_token %}
過濾器
- 語法:{ { 變數|過濾器 }},例如{ { name|lower }},表示將變數name的值變為小寫輸出
37、HTML轉義 關閉轉義
- 對於變數使用safe過濾器
{{ data|safe }}
- 對於程式碼塊使用autoescape標籤
{ % autoescape off %}
{{ body }}
{ % endautoescape %}
- 標籤autoescape接受on或者off引數
- 自動轉義標籤在base模板中關閉,在child模板中也是關閉的
38、csrf
- 跨站請求偽造
- 某些惡意網站上包含連結、表單按鈕或者JavaScript,它們會利用登入過的使用者在瀏覽器中的認證資訊試圖在你的網站上完成某些操作,這就是跨站攻擊
防csrf的使用
- 在django的模板中,提供了防止跨站攻擊的方法,使用步驟如下:
- step1:在settings.py中啟用’django.middleware.csrf.CsrfViewMiddleware’中介軟體,此項在建立專案時,預設被啟用
- step2:在csrf1.html中新增標籤
<form>
{% csrf_token %}
...
</form>
取消保護
- 如果某些檢視不需要保護,可以使用裝飾器csrf_exempt,模板中也不需要寫標籤,修改csrf2的檢視如下
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def csrf2(request):
uname=request.POST['uname']
return render(request,'booktest/csrf2.html',{'uname':uname})
39、驗證碼 驗證碼檢視
- 此段程式碼用到了PIL中的Image、ImageDraw、ImageFont模組,需要先安裝Pillow(3.4.1)包
- Image表示畫布物件
- ImageDraw表示畫筆物件
- ImageFont表示字型物件,ubuntu的字型路徑為“/usr/share/fonts/truetype/freefont”
- 程式碼如下:
from django.http import HttpResponse
def verifycode(request):
#引入繪圖模組
from PIL import Image, ImageDraw, ImageFont
#引入隨機函式模組
import random
#定義變數,用於畫面的背景色、寬、高
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), 255)
width = 100
height = 25
#建立畫面物件
im = Image.new('RGB', (width, height), bgcolor)
#建立畫筆物件
draw = ImageDraw.Draw(im)
#呼叫畫筆的point()函式繪製噪點
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
#定義驗證碼的備選值
str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
#隨機選取4個值作為驗證碼
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
#構造字型物件
font = ImageFont.truetype('FreeMono.ttf', 23)
#構造字型顏色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
#繪製4個字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
#釋放畫筆
del draw
#存入session,用於做進一步驗證
request.session['verifycode'] = rand_str
#記憶體檔案操作
import cStringIO
buf = cStringIO.StringIO()
#將圖片儲存在記憶體中,檔案型別為png
im.save(buf, 'png')
#將記憶體中的圖片資料返回給客戶端,MIME型別為圖片png
return HttpResponse(buf.getvalue(), 'image/png')
配置url
- 在urls.py中定義請求驗證碼檢視的url
from . import viewsUtil
urlpatterns = [
url(r'^verifycode/$', viewsUtil.verifycode),
]
顯示驗證碼
- 在模板中使用img標籤,src指向驗證碼檢視
<img id='verifycode' src="/verifycode/" alt="CheckCode"/>
40、管理靜態檔案 配置靜態檔案
- 在settings 檔案中定義靜態內容
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
- 在專案根目錄下建立static目錄,再建立當前應用名稱的目錄
- 在模板中可以使用硬編碼
/static/xxx/xxxx.jpg
- 在模板中可以使用static編碼
{ % load static from staticfiles %}
<img src="{ % static "my_app/myexample.jpg" %}" alt="My image"/>
41、中介軟體
- 是一個輕量級、底層的外掛系統,可以介入Django的請求和響應處理過程,修改Django的輸入或輸出
- 啟用:新增到Django配置檔案中的MIDDLEWARE_CLASSES元組中
- 每個中介軟體元件是一個獨立的Python類,可以定義下面方法中的一個或多個
-
- _init _:無需任何引數,伺服器響應第一個請求的時候呼叫一次,用於確定是否啟用當前中介軟體
-
- process_request(request):執行檢視之前被呼叫,在每個請求上呼叫,返回None或HttpResponse物件
-
- process_view(request, view_func, view_args, view_kwargs):呼叫檢視之前被呼叫,在每個請求上呼叫,返回None或HttpResponse物件
-
- process_template_response(request, response):在檢視剛好執行完畢之後被呼叫,在每個請求上呼叫,返回實現了render方法的響應物件
-
- process_response(request, response):所有響應返回瀏覽器之前被呼叫,在每個請求上呼叫,返回HttpResponse物件
-
- process_exception(request,response,exception):當檢視丟擲異常時呼叫,在每個請求上呼叫,返回一個HttpResponse物件
- 使用中介軟體,可以干擾整個處理過程,每次請求中都會執行中介軟體的這個方法
- 示例:自定義異常處理
- 與settings.py同級目錄下建立myexception.py檔案,定義類MyException,實現process_exception方法
from django.http import HttpResponse
class MyException():
def process_exception(request,response, exception):
return HttpResponse(exception.message)
- 將類MyException註冊到settings.py中介軟體中
MIDDLEWARE_CLASSES = (
'test1.myexception.MyException',
...
)
- 定義檢視,併發生一個異常資訊,則會執行自定義的異常處理
42、上傳圖片
- 當Django在處理檔案上傳的時候,檔案資料被儲存在request.FILES
- FILES中的每個鍵為中的name
- 注意:FILES只有在請求的方法為POST 且提交的帶有enctype=“multipart/form-data” 的情況下才會包含資料。否則,FILES 將為一個空的類似於字典的物件
- 使用模型處理上傳檔案:將屬性定義成models.ImageField型別
pic=models.ImageField(upload_to='cars/')
- 注意:如果屬性型別為ImageField需要安裝包Pilow
pip install Pillow==3.4.1
- 圖片儲存路徑
-
- 在專案根目錄下建立media資料夾
-
- 圖片上傳後,會被儲存到“/static/media/cars/圖片檔案”
-
- 開啟settings.py檔案,增加media_root項
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")
- 使用django後臺管理,遇到ImageField型別的屬性會出現一個file框,完成檔案上傳
- 手動上傳的模板程式碼
<html>
<head>
<title>檔案上傳</title>
</head>
<body>
<form method="post" action="upload/" enctype="multipart/form-data">
<input type="text" name="title"><br>
<input type="file" name="pic"/><br>
<input type="submit" value="上傳">
</form>
</body>
</html>
- 手動上傳的檢視程式碼
from django.conf import settings
def upload(request):
if request.method == "POST":
f1 = request.FILES['pic']
fname = '%s/cars/%s' % (settings.MEDIA_ROOT,f1.name)
with open(fname, 'w') as pic:
for c in f1.chunks():
pic.write(c)
return HttpResponse("ok")
else:
return HttpResponse("error")
43、Admin站點
- 通過使用startproject建立的專案模版中,預設Admin被啟用
- 1.建立管理員的使用者名稱和密碼
python manage.py createsuperuser
然後按提示填寫使用者名稱、郵箱、密碼
- 2.在應用內admin.py檔案完成註冊,就可以在後臺管理中維護模型的資料
from django.contrib import admin
from models import *
admin.site.register(HeroInfo)
- 查詢admin檔案:在INSTALLED_APPS項中加入django.contrib.admin,Django就會自動搜尋每個應用的admin模組並將其匯入
ModelAdmin物件
- ModelAdmin類是模型在Admin介面中的表示形式
- 定義:定義一個類,繼承於admin.ModelAdmin,註冊模型時使用這個類
class HeroAdmin(admin.ModelAdmin):
...
- 通常定義在應用的admin.py檔案裡
- 使用方式一:註冊引數
admin.site.register(HeroInfo,HeroAdmin)
- 使用方式二:註冊裝飾器
@admin.register(HeroInfo)
class HeroAdmin(admin.ModelAdmin):
- 通過重寫admin.ModelAdmin的屬性規定顯示效果,屬性主要分為列表頁、增加修改頁兩部分
列表頁選項
“操作選項”的位置
- actions_on_top、actions_on_bottom:預設顯示在頁面的頂部
class HeroAdmin(admin.ModelAdmin):
actions_on_top = True
actions_on_bottom = True
list_display
- 出現列表中顯示的欄位
- 列表型別
- 在列表中,可以是欄位名稱,也可以是方法名稱,但是方法名稱預設不能排序
- 在方法中可以使用format_html()輸出html內容
在models.py檔案中
from django.db import models
from tinymce.models import HTMLField
from django.utils.html import format_html
class HeroInfo(models.Model):
hname = models.CharField(max_length=10)
hcontent = HTMLField()
isDelete = models.BooleanField()
def hContent(self):
return format_html(self.hcontent)
在admin.py檔案中
class HeroAdmin(admin.ModelAdmin):
list_display = ['hname', 'hContent']
- 讓方法排序,為方法指定admin_order_field屬性
在models.py中HeroInfo類的程式碼改為如下:
def hContent(self):
return format_html(self.hcontent)
hContent.admin_order_field = 'hname'
- 標題欄名稱:將欄位封裝成方法,為方法設定short_description屬性