[toc]
1 靜態(tài)文件
定義:
css、js另伍、圖片查乒、json文件陷虎、字體文件等
存儲(chǔ)位置:
project/static/項(xiàng)目名/{css,js,img,json,font,other}
配置settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
栗子:
目錄結(jié)構(gòu):
Project
└─static
└─myApp
├─css
├─font
├─img
├─js
├─json
└─other
index.html
<head>
<meta charset="UTF-8">
<title>index</title>
<link rel="stylesheet" type="text/css" href="/static/myApp/css/style.css">
</head>
<script type="text/javascript" src="/static/myApp/js/lance.js"></script>
<body>
<h1>lance is a good man</h1>
<img src="/static/myApp/img/a.png" alt="">
</body>
style.css
h1{color: red;}
lance.js
console.log('good man')
普通文件動(dòng)態(tài)加載static目錄:(有錯(cuò)誤 先別用)
index.html
{% load static from staticfiles %}
<!DOCTYPE html>
...
<img src="{% static 'myApp/img/a.png' %}" alt="">
注意:
這時(shí)的文件的鏈接路徑 已經(jīng)不需要從static開(kāi)始去寫(xiě)了器予;
settings.py中的 STATICFILES_DIRS 配置項(xiàng)已經(jīng)無(wú)效偿枕;
2 中間件
2.1 概述
一個(gè)輕量級(jí)隙券、底層的插件榜聂,可以介入Django的請(qǐng)求響應(yīng);
2.2 方法
__init__
不需要傳參數(shù)陌凳,服務(wù)器響應(yīng)第一個(gè)請(qǐng)求的時(shí)候調(diào)用剥懒;用于確定是否啟用該中間件;
process_request(self, request)
在分配url匹配視圖之前合敦,每個(gè)請(qǐng)求上都會(huì)調(diào)用初橘;返回 None 或者 HttpResponse 對(duì)象;
process_view(self, request, view_func, views_args, view_kwargs)
調(diào)用視圖之前執(zhí)行,每個(gè)請(qǐng)求都會(huì)調(diào)用保檐;返回 None 或者 HttpResponse 對(duì)象耕蝉;
process_template(self, request, response)
在視圖執(zhí)行完成后調(diào)用,每個(gè)請(qǐng)求都會(huì)調(diào)用夜只;返回 None 或者 HttpResponse 對(duì)象垒在;
使用 render()
process_response(self, request, response)
在執(zhí)行模板之后調(diào)用,每個(gè)請(qǐng)求都會(huì)調(diào)用扔亥;返回 HttpResponse 對(duì)象场躯;
process_exception(self, request, exception)
當(dāng)視圖拋出異常時(shí)調(diào)用;返回 HttpResponse 對(duì)象旅挤;
2.3 自定義中間件
目錄結(jié)構(gòu):
project/middleware/myApp/
創(chuàng)建中間件:
myMiddler.py
from django.utils.deprecation import MiddlewareMixin
class MyMiddler(MiddlewareMixin):
def process_request(self, request):
print("GET參數(shù)為:", request.GET.get("a"))
使用中間件:
配置settings.py踢关,在 MIDDLEWARE 中添加:
'middleware.myApp.myMiddleware.MyMiddle',
驗(yàn)證:
刷新界面,可以看到后臺(tái)粘茄,有打印信息签舞;
3 上傳圖片
3.1 概述
文件上傳時(shí),文件數(shù)據(jù)存儲(chǔ)在request.FILES屬性中柒瓣;
注意:
form表單要上傳文件需要加 enctype="multipart/form-data" 儒搭;
上傳文件必須是POST請(qǐng)求;
3.2 存儲(chǔ)配置
存儲(chǔ)路徑
project/static/upfile
配置 settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upfile')
3.3 示例
upfile.html
<form action="/savefile/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="file">
<input type="submit" value="上傳">
</form>
views.py
def upfile(request):
return render(request, 'myApp/upfile.html')
import os
from django.conf import settings
def savefile(request):
if request.method == "POST":
f = request.FILES["file"]
# 文件在服務(wù)器端的路徑
filePath = os.path.join(settings.MEDIA_ROOT, f.name)
with open(filePath, 'wb') as fp:
for info in f.chunks(): # 分段讀取文件內(nèi)容
fp.write(info)
fp.flush()
return HttpResponse('上傳成功')
else:
return HttpResponse("上傳失敗")
urls.py
url(r'^upfile/$', views.upfile),
url(r'^savefile/$', views.savefile),
4 分頁(yè)
from django.core.paginator import Paginator
4.1 Paginator對(duì)象
創(chuàng)建對(duì)象
格式:
Paginator(列表, 整數(shù)) # (所有的數(shù)據(jù),每頁(yè)幾個(gè))
返回值:
返回分頁(yè)對(duì)象
屬性
count 對(duì)象總數(shù)
num_pages 頁(yè)面總數(shù)
page_range
頁(yè)碼列表
[1,2,3,4,5]
頁(yè)碼從1開(kāi)始
方法
page(num)
獲得一個(gè)Page對(duì)象嘹朗,如果提供的頁(yè)碼不存在师妙,會(huì)拋出一個(gè) 'InvalidPage' 異常
異常
InvalidPage
當(dāng)向 page() 傳遞一個(gè)無(wú)效的頁(yè)碼時(shí)拋出;
PageNotAnInteger
當(dāng)向 page() 傳遞一個(gè)不是整數(shù)的參數(shù)時(shí)拋出屹培;
EmptyPage
當(dāng)向 page() 傳遞一個(gè)有效,但是該頁(yè)面沒(méi)有數(shù)據(jù)時(shí)拋出怔檩;
4.2 Page對(duì)象
創(chuàng)建對(duì)象
Paginator對(duì)象的page方法返回得到Pafe對(duì)象褪秀;
不需要手動(dòng)創(chuàng)建;
屬性
object_list
當(dāng)前頁(yè)上的所有的數(shù)據(jù)(對(duì)象)列表薛训;
number
當(dāng)前頁(yè)的頁(yè)碼值媒吗;
paginator
當(dāng)前page對(duì)象關(guān)聯(lián)的paginator對(duì)象;
方法
has_next()
判斷是否有下一頁(yè)乙埃,如果有返回True闸英;
has_previous()
判斷是否有上一頁(yè),如果有返回True介袜;
has_other_pages()
判斷是否有上一頁(yè)或者下一頁(yè)甫何,如果有返回True;
next_page_number()
返回下一頁(yè)的頁(yè)碼遇伞,如故下一頁(yè)不存在辙喂,拋出InvalidPage異常;
previous_page_number()
返回上一頁(yè)的頁(yè)碼,如故上一頁(yè)不存在巍耗,拋出InvalidPage異常秋麸;
len()
返回當(dāng)前頁(yè)的數(shù)據(jù)個(gè)數(shù);
4.3 Paginator對(duì)象與Page對(duì)象的關(guān)系
Paginator對(duì)象 把 Student.object.all() 返回的列表分割炬太;
使用 Paginator對(duì)象的 page方法灸蟆,生成對(duì)應(yīng)列表段的 Page對(duì)象;
每個(gè)Page對(duì)象亲族,對(duì)應(yīng)列表段中的內(nèi)容炒考;
4.4 示例:分頁(yè)顯示學(xué)生信息
studentpage.html
<ul><li>{{ pagenum }}</li></ul>
<ul>
{% for stu in student %}
<li>{{ stu.id }} | {{ stu.sname }} | {{ stu.sgrade }}</li>
{% endfor %}
</ul>
<ul>
{% for index in student.paginator.page_range %}
{# 調(diào)用page對(duì)象的paginator方法,到達(dá)paginator類孽水;#}
{# 再使用paginator類的page_range方法票腰;#}
<li><a href="/studentpage/{{ index }}/">{{ index }}</a></li>
{% endfor %}
</ul>
views.py
from django.core.paginator import Paginator
def studentpage(request, pageid):
# 所有學(xué)生的列表
allList = Student.stuObj.all()
paginator = Paginator(allList, 3)
page = paginator.page(pageid)
pagenum = page.number
return render(request, 'myapp/studentpage.html', {"student": page, "pagenum": pagenum})
urls.py
url(r'^studentpage/(\d+)/$', views.studentpage),
5 ajax
需要?jiǎng)討B(tài)生成,請(qǐng)求json數(shù)據(jù)
栗子:
views.py
from django.http import JsonResponse
def ajaxstudet(request):
stus = Student.stuObj.all()
list = []
for stu in stus:
list.append([stu.id, stu.sname, stu.sgrade])
return JsonResponse({"data": list})
6 富文本
pip install django-tinymce
在站點(diǎn)中使用
配置settings.py文件
在INSTALLED_APPS中添加:'tinymce',
在末尾追加:
# 富文本
TINYMCE_DEFAULT_CONFIG = {
'theme': 'advanced',
'width': 600,
'height': 400,
}
創(chuàng)建一個(gè)模型類(myApp/models.py):
from tinymce.models import HTMLField
class Text(models.Model):
str = HTMLField()
配置站點(diǎn)(myApp/admin.py):
from .models import Text
admin.site.register(Text)
在自定義視圖中使用
urls.py
url(r'^edit/$', views.edit),
views.py
def edit(request):
return render(request, 'myApp/edit.html')
edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>富文本</title>
<script type="text/javascript" src="/static/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
tinyMCE.init({
'mode': 'textareas',
'theme': 'advanced',
'width': 600,
'height': 400,
})
</script>
</head>
<body>
<form action="">
<textarea name="str">lance is good man</textarea>
<input type="submit" value="提交">
</form>
</body>
</html>
7 celery
問(wèn)題:
1. 用戶發(fā)起request女气,并且要等待response返回杏慰;但是在視圖中有一些耗時(shí)的操作,導(dǎo)致用戶可能會(huì)等待很長(zhǎng)時(shí)間才能接受response炼鞠,這樣用戶體驗(yàn)很差缘滥;
2. 網(wǎng)站每隔一段時(shí)間要同步數(shù)據(jù),但是http請(qǐng)求是需要觸發(fā)的谒主;
celery解決:
問(wèn)題1: 將耗時(shí)的操作朝扼,放到celery中執(zhí)行;
問(wèn)題2: 使用celery定時(shí)執(zhí)行霎肯;
celery組件:
任務(wù)tasl 本質(zhì)是一個(gè)Python函數(shù)擎颖,將耗時(shí)操作封裝成一個(gè)函數(shù);
隊(duì)列queue 將要執(zhí)行的任務(wù)观游,放到隊(duì)列里搂捧;
工人woeker 負(fù)責(zé)執(zhí)行隊(duì)列中的任務(wù);
代理broker 負(fù)責(zé)調(diào)度懂缕,在部署環(huán)境中使用redies;
安裝:
pip install celery
pip install celery-with-redis
pip install django-celery
配置settings.py:
INSTALLED_APPS
'djcelery',
追加
import djcelery
djcelery.setup_loader() #初始化
BROKER_URL = 'redis://:user@IP:6379/0'
CELERY_IMPORTS = ('myApp.task',)
創(chuàng)建task.py
project/myApp/task.py
遷移允跑,生成celery需要的數(shù)據(jù)庫(kù)表:
python manage.py migrate
在 /project/project 下創(chuàng)建 celery.py:
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault( 'DJANGO_SETTINGS_MODULES', 'whthas_home.settings')
app = Celery('portal')
app.config_from_onject('django.conf:settings')
app.authodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
在project/project/__init__.py中添加:
from .celery import import app as celery_app