一、靜態(tài)文件
- 簡(jiǎn)述
CSS、JS陶夜、JSON桃序、圖片、字體文件...
- 配置
settings.py
STATIC_URL='/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
- 示例
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>餓了嗎 | 首頁</title>
<link rel="stylesheet" type="text/css" href="{% static 'elema/css/style.css' %}"/>
<script type="text/javascript" src="{% static 'elema/js/jquery-3.1.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'elema/js/index.js' %}"></script>
</head>
<body>
<h1>餓了嗎溯职?</h1>
<img src="{% static 'elema/img/1.jpeg' %}">
</body>
</html>
在項(xiàng)目文件中創(chuàng)建static精盅,并創(chuàng)建對(duì)應(yīng)的應(yīng)用目錄,在應(yīng)用目錄里面添加例如js谜酒、img叹俏、css等目錄
二、中間件
- 概述
中間件是一個(gè)用來處理Django的請(qǐng)求和響應(yīng)的框架級(jí)別的鉤子僻族。
它是一個(gè)輕量粘驰、低級(jí)別的插件系統(tǒng),用于在全局范圍內(nèi)改變Django的輸入和輸出述么。
每個(gè)中間件組件都負(fù)責(zé)做一些特定的功能蝌数。
但是由于其影響的是全局,所以需要謹(jǐn)慎使用顶伞,使用不當(dāng)會(huì)影響性能枝哄。
本質(zhì): 就是一個(gè)python類
應(yīng)用場(chǎng)景: 統(tǒng)計(jì)挠锥、黑名單侨赡、白名單、反爬...
- 方法
- __init__
不需要傳參蓖宦,服務(wù)器響應(yīng)第一個(gè)請(qǐng)求的時(shí),會(huì)自動(dòng)調(diào)用稠茂,用于確定是否啟用中間件
- process_request(self,request)
在視圖執(zhí)行前調(diào)用(即分配url匹配視圖之前),每個(gè)請(qǐng)求都會(huì)調(diào)用柠偶,返回None或HttpResponse對(duì)象
- process_view(self,request,view_func,view_args,view_kwargs)
調(diào)用視圖之前執(zhí)行,每個(gè)請(qǐng)求都會(huì)調(diào)用,返回None或HttpResponse對(duì)象
- process_templae_response(self,request,response)
在視圖剛好執(zhí)行完后調(diào)用睬关,每個(gè)請(qǐng)求都會(huì)調(diào)用诱担,返回None或HttpResponse對(duì)象
- process_response(self,request,response)
所有響應(yīng)返回瀏覽器之前調(diào)用,每個(gè)請(qǐng)求都會(huì)調(diào)用电爹,返回None或HttpResponse對(duì)象
- process_exception(self,request,exception)
當(dāng)視圖出現(xiàn)異常時(shí)調(diào)用蔫仙,返回HttpResponse對(duì)象
備注: 為什么會(huì)返回HttpRespons對(duì)象?因?yàn)樵谡?qǐng)求進(jìn)來后如果有問題丐箩,就可以不做后續(xù)處理摇邦,直接給客戶端響應(yīng)。
settings.py
中的MIDDLEWARE = [...]就中間件屎勘。
-
方法執(zhí)行
中間件方法執(zhí)行.png 自定義中間件并使用
在工程目錄下middleware目錄下創(chuàng)建應(yīng)用目錄
- 在middleware/elema中創(chuàng)建一個(gè)elemamiddleware.py
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
# 在視圖執(zhí)行前調(diào)用
def process_request(self,reqeust):
print('get請(qǐng)求施籍,參數(shù)name: ', reqeust.GET.get('name'))
- 配置settings.py文件(即在MIDDLEWARE中添加上述文件的位置)
'middleware.elema.elemamiddleware.MyMiddle'
- 瀏覽器
http://127.0.0.1:8000/?name=zyz
- 效果
在終端中可以看到`get請(qǐng)求,參數(shù)name: zyz`
- 中間件(黑名單攔截)
# 攔截器挑秉,攔截他黑名單中的IP
class MyMiddle(MiddlewareMixin):
def process_request(self, request):
if request.META['REMOTE_ADDR'] in getattr(settings, 'BLOCKED_IPS', []):
return HttpResponse('<h1>Forbidden</h1>')
# settings.py中
BLOCKED_IPS = [ # IP黑名單
'192.168.0.100'
]
- 中間件(未登陸處理)
class MyMiddle(MiddlewareMixin):
def process_request(self, request):
# request.META['REMOTE_ADDR'] 請(qǐng)求的IP地址
if request.path !='/meituan/login/': # 檢測(cè)如果不是登錄的話
if "username" in request.COOKIES: # 已經(jīng)登錄不做任何處理
pass
else: # 未登錄法梯,重定向到登錄頁面
return HttpResponseRedirect('/meituan/login/')
三、上傳圖片
- 注意
- 文件上傳時(shí)犀概,文件數(shù)據(jù)存儲(chǔ)在request.FILES屬性中
- form表單要上傳文件需要加 enctype="multipart/form-data"
- 上傳文件必須是post請(qǐng)求
- 存儲(chǔ)路徑
- 在static目錄下創(chuàng)建upfile目錄用于存儲(chǔ)接受上傳的文件
- 配置settings.py文件
MDEIA_ROOT = os.path.join(BASE_DIR,'static/upfile')
- 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上傳</title>
</head>
<body>
<form action="{% url 'elema:savefile' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" value="上傳文件" name="file">
<input type="submit" value="上傳">
</form>
</body>
</html>
# 文件上傳
def upfile(request):
return render(request, 'elema/upfile.html')
# 文件保存
import os
from django.conf import settings # 導(dǎo)入settings.py
def savefile(request):
# 判斷是否為POST
if request.method == 'POST':
# 獲取文件內(nèi)容
file = request.FILES['file']
# 文件保存路徑
filepath = os.path.join(settings.MDEIA_ROOT,file.name)
# 文件寫入
with open(filepath,'wb') as fp:
for info in file.chunks():
fp.write(info)
return HttpResponse('文件上傳成功')
else:
return HttpResponse('文件上傳失敗')
四、分頁
- Paginator創(chuàng)建對(duì)象
格式: Paginator(列表,每頁個(gè)數(shù))
返回值: 分頁對(duì)象
- Paginator屬性
count: 對(duì)象總數(shù)
num_pages: 頁面總數(shù)
page_range: 頁碼列表(頁碼從1開始)
- Paginator方法
page(num): 獲得一個(gè)Page對(duì)象,如果提供的頁面不存在會(huì)拋出'InvalidPage'異常
- Paginator異常
InvalidPage: 當(dāng)向page()傳遞是一個(gè)無效頁碼時(shí)拋出
PageNotAnInteger: 當(dāng)向page()傳遞的不是一個(gè)整數(shù)時(shí)拋出
EmptyPage: 當(dāng)向page()傳遞一個(gè)有效值这嚣,但該頁面沒有數(shù)據(jù)時(shí)拋出
- Page創(chuàng)建對(duì)象
Paginator對(duì)象的page()方法返回得到Page對(duì)象(不需要手動(dòng)創(chuàng)建)
- Page屬性
object_list: 當(dāng)前頁上所有的數(shù)據(jù)(對(duì)象)列表
number: 當(dāng)前頁的頁碼值
paginator: 當(dāng)前page對(duì)象關(guān)聯(lián)的paginator對(duì)象
- Page方法
has_next(): 判斷是否有下一頁障涯,如果有返回True
has_previous(): 判斷是否有上一頁九秀,如果有返回True
has_other_pages(): 判斷是否有上一頁或下一頁痹换,如果有返回True
next_page_number(): 返回下一頁的頁碼缔杉,如果下一頁不存在拋出InvalidPage異常
previous_page_number(): 返回上一頁的頁碼,如果上一頁不存在拋出InvalidPage異常
len(): 返回當(dāng)前頁的數(shù)據(jù)(對(duì)象)個(gè)數(shù)
- Paginator對(duì)象與Page對(duì)象關(guān)系
- 示例
# urls.py文件
url(r'^goodslist/(\d+)/$',views.goodslist, name='goodslist'), # 商品列表
# views.py文件
# 商品列表
from .models import Goods
from django.core.paginator import Paginator
def goodslist(request,page):
# 所有商品數(shù)據(jù)
alllist = Goods.objects.all()
# 10條數(shù)據(jù)為一頁,劃分總頁數(shù)
# 分頁對(duì)象
paginator = Paginator(list(alllist),10)
# 根據(jù)傳入的頁碼得到Page對(duì)象
pageobj = paginator.page(page)
# return HttpResponse('page:'+page)
return render(request,'elema/goodslist.html',{'pageobj':pageobj})
# models.py文件
# 商品 模型類
class Goods(models.Model):
# 商品名稱
name = models.CharField(max_length=20)
# 商品圖片
icon = models.CharField(max_length=255)
# 商品價(jià)格
price = models.IntegerField()
# 商品描述
detail = models.CharField(max_length=255)
class Meta:
db_table = 'goods'
# 存儲(chǔ)過程: 創(chuàng)建商品數(shù)據(jù)(產(chǎn)生批量數(shù)據(jù))
# 第一步: 創(chuàng)建上述Goods模型類 【注意表名是goods】
# 第二步: 生成遷移文件,并執(zhí)行遷移
# 第三步: 進(jìn)入到對(duì)應(yīng)的數(shù)據(jù)庫中,檢查表單結(jié)構(gòu)是否一致
mysql> desc goods;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| icon | varchar(255) | NO | | NULL | |
| price | int(11) | NO | | NULL | |
| detail | varchar(255) | NO | | NULL | |
+--------+--------------+------+-----+---------+----------------+
# 第四步: 將圖片 'cymbal.png'等,放置在'/static/img'目錄
# 第五步: 創(chuàng)建 存儲(chǔ)過程 添加到數(shù)據(jù)庫中(復(fù)制到mysql終端中)
# insert into elema_goods(name,icon,price,detail) value(_name,_icon,_price,_detail)
delimiter //
create procedure add_goods(num int(4))
begin
# 定義變量
declare _i,_price,_temp int(4) default 0;
declare _name,_icon,_detail varchar(255) default '';
declare BASE_PATH varchar(255) default '/static/img/';
# 循環(huán)
while _i<num do
# 設(shè)置變量
set _temp = round(rand()*10000+1000);
set _name = concat(_temp,'-商品名稱');
set _temp = round(rand()*5+1);
case _temp
when 1 then
set _icon = concat(BASE_PATH,'1.jpg');
when 2 then
set _icon = concat(BASE_PATH,'2.jpg');
when 3 then
set _icon = concat(BASE_PATH,'3.jpg');
when 4 then
set _icon = concat(BASE_PATH,'4.jpg');
when 5 then
set _icon = concat(BASE_PATH,'5.jpg');
when 6 then
set _icon = concat(BASE_PATH,'6.jpg');
else
set _icon = concat(BASE_PATH,'1.jpg');
end case;
set _temp = round(rand()*10000+1000);
set _price = _temp;
set _temp = round(rand()*10000+1000);
set _detail = concat(_temp,'-Apple/蘋果 iPhone 7 Plus蘋果7代7pluss國行美版三網(wǎng)5.5寸7p手機(jī)');
# 插入數(shù)據(jù)
insert into goods(name,icon,price,detail) value(_name,_icon,_price,_detail);
# 修改次數(shù)
set _i = _i + 1;
end while;
# 顯示數(shù)據(jù)
select * from goods;
end
//
delimiter ;
# 第六步: 調(diào)用存儲(chǔ)過程 【根據(jù)自己需求添加對(duì)應(yīng)個(gè)數(shù)即可】
call add_goods(30);
# goodslist.html文件
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>餓了嗎 | 商品列表</title>
<link rel="stylesheet" type="text/css" href="{% static 'elema/css/goodslist.css' %}">
</head>
<body>
<h1>當(dāng)前頁: {{pageobj.number}}</h1>
<!--顯示內(nèi)容-->
<ul class="content">
{% for goods in pageobj.object_list %}
<li>
<div>
<img src="{{goods.icon}}">
<span> {{goods.name}} - ¥{{goods.price}}</span>
</div>
<p> {{goods.detail}} </p>
</li>
{% endfor %}
</ul>
<!--分頁頁碼-->
<ul class="pageview">
{% for index in pageobj.paginator.page_range %}
<!--當(dāng)前頁面-->
{% if index == pageobj.number %}
<li class="active"> {{index}} </li>
{% else %}
<li>
<a href="{% url 'elema:goodslist' index %}">{{index}}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</body>
</html>
五、ajax請(qǐng)求
- 概述
網(wǎng)頁中需要?jiǎng)討B(tài)生成時(shí),會(huì)向服務(wù)器請(qǐng)求對(duì)應(yīng)JSON數(shù)據(jù)
- 示例
# urls.py文件
url(r'^goodsjson/$',views.goodsjson, name='goodsjson'), # 商品列表json數(shù)據(jù)操作頁面(ajax操作)
url(r'^goodsinfo/$',views.goodsinfo, name='goodsinfo'), # 商品列表json數(shù)據(jù)
# views.py文件
# 商品列表json數(shù)據(jù)(ajax操作)
def goodsjson(request):
return render(request,'elema/goodsjson.html')
# 返回商品列表json數(shù)據(jù)
from django.http import JsonResponse
def goodsinfo(request):
# 所有商品數(shù)據(jù)
alllist = Goods.objects.all()
# 拼接成列表
list = []
for goods in alllist:
list.append({'name':goods.name,'price':goods.price})
return JsonResponse({'data':list})
# goodsjson.html文件
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>商品列表JSON數(shù)據(jù)</title>
<script type="text/javascript" src="{% static 'elema/js/jquery-3.1.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'elema/js/goodsjson.js' %}"></script>
</head>
<body>
<h1>商品信息列表</h1>
<button id="bt">顯示商品列表</button>
</body>
</html>
# goodsjson.js文件
$(function(){
$('#bt').click(function(){
// jquery中ajax快捷操作
$.ajax({
type:"get",
url:"/elema/goodsinfo",
dataType: 'json',
success: function(data, status){
console.log(data);
// 獲取返回的數(shù)據(jù)
var datasource = data['data'];
for(var i=0; i<datasource.length; i++){
var oP = document.createElement('p');
oP.innerHTML = datasource[i]['name'] + " ¥" + datasource[i]['price'];
document.body.appendChild(oP);
}
}
});
});
});