07-Django高級使用

一、靜態(tài)文件

  • 簡述
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>

在項目文件中創(chuàng)建static,并創(chuàng)建對應(yīng)的應(yīng)用目錄,在應(yīng)用目錄里面添加例如js、img、css等目錄

二、中間件

  • 概述
    中間件是一個用來處理Django的請求和響應(yīng)的框架級別的鉤子。
    它是一個輕量、低級別的插件系統(tǒng),用于在全局范圍內(nèi)改變Django的輸入和輸出。
    每個中間件組件都負(fù)責(zé)做一些特定的功能。
    但是由于其影響的是全局,所以需要謹(jǐn)慎使用,使用不當(dāng)會影響性能。

本質(zhì): 就是一個python類
應(yīng)用場景: 統(tǒng)計、黑名單、白名單、反爬...

  • 方法
- __init__
    不需要傳參,服務(wù)器響應(yīng)第一個請求的時,會自動調(diào)用,用于確定是否啟用中間件
- process_request(self,request)
    在視圖執(zhí)行前調(diào)用(即分配url匹配視圖之前),每個請求都會調(diào)用,返回None或HttpResponse對象
- process_view(self,request,view_func,view_args,view_kwargs)
    調(diào)用視圖之前執(zhí)行,每個請求都會調(diào)用,返回None或HttpResponse對象
- process_templae_response(self,request,response)
    在視圖剛好執(zhí)行完后調(diào)用,每個請求都會調(diào)用,返回None或HttpResponse對象
- process_response(self,request,response)
    所有響應(yīng)返回瀏覽器之前調(diào)用,每個請求都會調(diào)用,返回None或HttpResponse對象
- process_exception(self,request,exception)
    當(dāng)視圖出現(xiàn)異常時調(diào)用,返回HttpResponse對象
    
備注: 為什么會返回HttpRespons對象?因?yàn)樵谡埱筮M(jìn)來后如果有問題,就可以不做后續(xù)處理,直接給客戶端響應(yīng)。

settings.py中的MIDDLEWARE = [...]就中間件。

  • 方法執(zhí)行


    中間件方法執(zhí)行.png
  • 自定義中間件并使用

在工程目錄下middleware目錄下創(chuàng)建應(yīng)用目錄
- 在middleware/elema中創(chuàng)建一個elemamiddleware.py
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
    # 在視圖執(zhí)行前調(diào)用
    def process_request(self,reqeust):
        print('get請求,參數(shù)name: ', reqeust.GET.get('name'))

- 配置settings.py文件(即在MIDDLEWARE中添加上述文件的位置)
    'middleware.elema.elemamiddleware.MyMiddle'

- 瀏覽器
    http://127.0.0.1:8000/?name=zyz

- 效果  
    在終端中可以看到`get請求,參數(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']  請求的IP地址
        if request.path !='/meituan/login/': # 檢測如果不是登錄的話
            if "username" in request.COOKIES:   # 已經(jīng)登錄不做任何處理
                pass
            else:   # 未登錄,重定向到登錄頁面
                return HttpResponseRedirect('/meituan/login/')

三、上傳圖片

  • 注意
- 文件上傳時,文件數(shù)據(jù)存儲在request.FILES屬性中
- form表單要上傳文件需要加 enctype="multipart/form-data"
- 上傳文件必須是post請求
  • 存儲路徑
- 在static目錄下創(chuàng)建upfile目錄用于存儲接受上傳的文件
- 配置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)建對象
格式: Paginator(列表,每頁個數(shù))
返回值: 分頁對象
  • Paginator屬性
count: 對象總數(shù)
num_pages: 頁面總數(shù)
page_range: 頁碼列表(頁碼從1開始)
  • Paginator方法
page(num): 獲得一個Page對象,如果提供的頁面不存在會拋出'InvalidPage'異常
  • Paginator異常
InvalidPage: 當(dāng)向page()傳遞是一個無效頁碼時拋出
PageNotAnInteger: 當(dāng)向page()傳遞的不是一個整數(shù)時拋出
EmptyPage: 當(dāng)向page()傳遞一個有效值,但該頁面沒有數(shù)據(jù)時拋出
  • Page創(chuàng)建對象
Paginator對象的page()方法返回得到Page對象(不需要手動創(chuàng)建)
  • Page屬性
object_list: 當(dāng)前頁上所有的數(shù)據(jù)(對象)列表
number: 當(dāng)前頁的頁碼值
paginator: 當(dāng)前page對象關(guān)聯(lián)的paginator對象
  • Page方法
has_next(): 判斷是否有下一頁,如果有返回True
has_previous(): 判斷是否有上一頁,如果有返回True
has_other_pages(): 判斷是否有上一頁或下一頁,如果有返回True
next_page_number(): 返回下一頁的頁碼,如果下一頁不存在拋出InvalidPage異常
previous_page_number(): 返回上一頁的頁碼,如果上一頁不存在拋出InvalidPage異常
len(): 返回當(dāng)前頁的數(shù)據(jù)(對象)個數(shù)
  • Paginator對象與Page對象關(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ù)
    # 分頁對象
    paginator = Paginator(list(alllist),10)

    # 根據(jù)傳入的頁碼得到Page對象
    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)
    # 商品價格
    price = models.IntegerField()
    # 商品描述
    detail = models.CharField(max_length=255)

    class Meta:
        db_table = 'goods' 
# 存儲過程: 創(chuàng)建商品數(shù)據(jù)(產(chǎn)生批量數(shù)據(jù))
# 第一步: 創(chuàng)建上述Goods模型類 【注意表名是goods】
# 第二步: 生成遷移文件,并執(zhí)行遷移
# 第三步: 進(jìn)入到對應(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)建 存儲過程 添加到數(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)用存儲過程 【根據(jù)自己需求添加對應(yīng)個數(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請求

  • 概述
網(wǎng)頁中需要動態(tài)生成時,會向服務(wù)器請求對應(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);
                }
            }
        });
    });
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 面試報名 4月18日—21日 面試考試 5月20日—21日
    貓七_(dá)698b閱讀 106評論 0 0
  • 這個暑假我去了,老家。我們做了很長時間的車。到了那后我就去我外婆家。坐一坐,玩一會兒,然后就在那住了下來 還有我奶...
  • 愛情,剛開始或許是一種吸引,一種外貌的吸引,久而久之,便是一種舒適。沒有刻意的討好,沒有刻意的委屈。
    馮凡平閱讀 233評論 0 1
  • 【青春校園】我不怕孤身一人,只怕沒有你(目錄) 璇子本來想到了搭上地鐵之后再跟陳辰講她下班的消息的,所以陳辰發(fā)信息...
    薄小荷閱讀 304評論 8 7

友情鏈接更多精彩內(nèi)容