Django教程七(分頁(yè),文件上傳)

目錄

分頁(yè)

  • 分頁(yè)是指在web頁(yè)面有大量數(shù)據(jù)需要顯示時(shí),當(dāng)一頁(yè)的內(nèi)容太多不利于閱讀和不利于數(shù)據(jù)提取的情況下,可以分為多頁(yè)進(jìn)行顯示。
  • Django提供了一些類來(lái)幫助你管理分頁(yè)的數(shù)據(jù) — 也就是說(shuō),數(shù)據(jù)被分在不同頁(yè)面中,并帶有“上一頁(yè)/下一頁(yè)”鏈接。
  • 這些類位于django/core/paginator.py中。

Paginator對(duì)象

  • 對(duì)象的構(gòu)造方法

    • Paginator(object_list, per_page)
    • 參數(shù)
      • object_list 對(duì)象列表
      • per_page 每頁(yè)數(shù)據(jù)個(gè)數(shù)
    • 返回值:
      • 分頁(yè)對(duì)象
  • Paginator屬性

    • count:對(duì)象總數(shù)
    • num_pages:頁(yè)面總數(shù)
    • page_range:從1開始的range對(duì)象, 用于記錄當(dāng)前面碼數(shù)
    • per_page 每頁(yè)個(gè)數(shù)
  • Paginator方法

    • Paginator.page(number)
      • 參數(shù) number為頁(yè)碼信息(從1開始)
      • 返回當(dāng)前number頁(yè)對(duì)應(yīng)的頁(yè)信息
      • 如果提供的頁(yè)碼不存在,拋出InvalidPage異常
  • Paginator異常exception

    • InvalidPage:當(dāng)向page()傳入一個(gè)無(wú)效的頁(yè)碼時(shí)拋出
    • PageNotAnInteger:當(dāng)向page()傳入一個(gè)不是整數(shù)的值時(shí)拋出
    • EmptyPage:當(dāng)向page()提供一個(gè)有效值,但是那個(gè)頁(yè)面上沒有任何對(duì)象時(shí)拋出

Page對(duì)象

  • 創(chuàng)建對(duì)象
    Paginator對(duì)象的page()方法返回Page對(duì)象,不需要手動(dòng)構(gòu)造

  • Page對(duì)象屬性

    • object_list:當(dāng)前頁(yè)上所有對(duì)象的列表
    • number:當(dāng)前頁(yè)的序號(hào),從1開始
    • paginator:當(dāng)前page對(duì)象相關(guān)的Paginator對(duì)象
  • Page對(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è)面對(duì)象的個(gè)數(shù)
  • 說(shuō)明:

    • Page 對(duì)象是可迭代對(duì)象,可以用 for 語(yǔ)句來(lái) 訪問(wèn)當(dāng)前頁(yè)面中的每個(gè)對(duì)象
  • 參考文檔https://docs.djangoproject.com/en/1.11/topics/pagination/

  • 分頁(yè)示例:
    • 視圖函數(shù)
    def book(request):
        bks = models.Book.objects.all()
        paginator = Paginator(bks, 10)
        print('當(dāng)前對(duì)象的總個(gè)數(shù)是:', paginator.count)
        print('當(dāng)前對(duì)象的面碼范圍是:', paginator.page_range)
        print('總頁(yè)數(shù)是:', paginator.num_pages)
        print('每頁(yè)最大個(gè)數(shù):', paginator.per_page)
    
        cur_page = request.GET.get('page', 1)  # 得到默認(rèn)的當(dāng)前頁(yè)
        page = paginator.page(cur_page)
        return render(request, 'bookstore/book.html', locals())
    
    • 模板設(shè)計(jì)
    <html>
    <head>
        <title>分頁(yè)顯示</title>
    </head>
    <body>
    {% for b in page %}
        <div>{{ b.title }}</div>
    {% endfor %}
    
    {# 分頁(yè)功能 #}
    {# 上一頁(yè)功能 #}
    {% if page.has_previous %}
    <a href="{% url "book" %}?page={{ page.previous_page_number }}">上一頁(yè)</a>
    {% else %}
    上一頁(yè)
    {% endif %}
    
    {% for p in paginator.page_range %}
        {% if p == page.number %}
            {{ p }}
        {% else %}
            <a href="{% url "book" %}?page={{ p }}">{{ p }}</a>
        {% endif %}
    {% endfor %}
    
    {#下一頁(yè)功能#}
    {% if page.has_next %}
    <a href="{% url "book" %}?page={{ page.next_page_number }}">下一頁(yè)</a>
    {% else %}
    下一頁(yè)
    {% endif %}
    總頁(yè)數(shù): {{ page.len }}
    </body>
    </html>
    

day08

文件上傳

  • 文件上傳必須為POST提交方式

  • 表單<form>中文件上傳時(shí)必須有帶有enctype="multipart/form-data" 時(shí)才會(huì)包含文件內(nèi)容數(shù)據(jù)。

  • 表單中用<input type="file" name="xxx">標(biāo)簽上傳文件

    • 名字xxx對(duì)應(yīng)request.FILES['xxx'] 對(duì)應(yīng)的內(nèi)存緩沖文件流對(duì)象??梢阅苓^(guò)request.FILES['xxx'] 返回的對(duì)象獲取上傳文件數(shù)據(jù)
    • file=request.FILES['xxx'] file 綁定文件流對(duì)象,可以通過(guò)文件流對(duì)象的如下信息獲取文件數(shù)據(jù)
      file.name 文件名
      file.file 文件的字節(jié)流數(shù)據(jù)
  • 如下上傳文件為圖片類型,可以用模塊類屬性定義成models.ImageField類型

    • image_file = models.ImageField(upload_to='images/')
    • 注意:如果屬性類型為ImageField需要安裝包Pilow
    • pip install Pillow==3.4.1
    • 圖片存儲(chǔ)路徑
  • 練習(xí):
    在項(xiàng)目根目錄下創(chuàng)建static文件夾
    圖片上傳后,會(huì)被保存到“/static/files/"下
    打開settings.py文件,增加MEDIA_ROOT項(xiàng)
    MEDIA_ROOT=os.path.join(BASE_DIR,"static/files")
    使用django后臺(tái)管理,遇到ImageField類型的屬性會(huì)出現(xiàn)一個(gè)file框,完成文件上傳
    手動(dòng)上傳的模板代碼

  • 上傳文件的表單書寫方式

<!-- file:static/upload.html -->
<html>
<head>
    <title>文件上傳</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>上傳文件</h1>
    <form method="post" action="/upload" enctype="multipart/form-data">
        <input type="file" name="myfile"/><br>
        <input type="submit" value="上傳">
    </form>
</body>
</html>
  • 在setting.py 中設(shè)置一個(gè)變量MEDIA_ROOT 用來(lái)記錄上傳文件的位置
# file : settings.py
...
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/files')
...
  • 在當(dāng)前項(xiàng)目文件夾下創(chuàng)建 static/files 文件夾
$ mkdir -p static/files
  • 添加路由及對(duì)應(yīng)的處理函數(shù)
# file urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^upload', views.upload_file)
]
  • 上傳文件的視圖處理函數(shù)
# file views.py
from django.http import HttpResponse, Http404
from django.conf import settings
import os

# from  django.views.decorators.http import require_POST
# @require_POST
def upload_file(request):
    if request.method == "POST":
        file = request.FILES['myfile']
        print("上傳文件名是:", file.name)

        filename =os.path.join(settings.MEDIA_ROOT, file.name)
        with open(filename, 'wb') as f:
            f.write(file.file.read())
            return HttpResponse("接收文件成功")
    raise Http404

項(xiàng)目部署

  • 項(xiàng)目部置在軟件開發(fā)完畢后,將開發(fā)機(jī)器上運(yùn)行的開發(fā)板軟件實(shí)際安裝到服務(wù)器上進(jìn)行長(zhǎng)期運(yùn)行
  • 部署要分以下幾個(gè)步驟進(jìn)行
    1. 在安裝機(jī)器上安裝和配置同版本的數(shù)據(jù)庫(kù)
    2. django 項(xiàng)目遷移(在安裝機(jī)器上配置與開發(fā)環(huán)境相同的python版本及依懶的包)
    3. 用 uwsgi 替代python3 manage.py runserver 方法啟動(dòng)服務(wù)器
    4. 配置 nginx 反向代理服務(wù)器
    5. 用nginx 配置靜態(tài)文件路徑,解決靜態(tài)路徑問(wèn)題
  1. 安裝同版本的數(shù)據(jù)庫(kù)
    • 安裝步驟略
  2. django 項(xiàng)目遷移
    1. 安裝python
      • $ sudo apt install python3
    2. 安裝相同版本的包
      • 導(dǎo)出當(dāng)前模塊數(shù)據(jù)包的信息:
        • $ pip3 freeze > package_list.txt
      • 導(dǎo)入到另一臺(tái)新主機(jī)
        • $ pip3 install -r package_list.txt
    3. 將當(dāng)前項(xiàng)目源代碼復(fù)制到運(yùn)程主機(jī)上(scp 命令)
      • $ sudo scp -a 當(dāng)前項(xiàng)目源代碼 遠(yuǎn)程主機(jī)地址和文件夾

WSGI Django工作環(huán)境部署

  • WSGI (Web Server Gateway Interface)Web服務(wù)器網(wǎng)關(guān)接口,是Python應(yīng)用程序或框架和Web服務(wù)器之間的一種接口,被廣泛使用
  • 它實(shí)現(xiàn)了WSGI協(xié)議、http等協(xié)議。Nginx中HttpUwsgiModule的作用是與uWSGI服務(wù)器進(jìn)行交換。WSGI是一種Web服務(wù)器網(wǎng)關(guān)接口。

uWSGI 網(wǎng)關(guān)接口配置

  • 使用 python manage.py runserver 通常只在開發(fā)和測(cè)試環(huán)境中使用。

  • 當(dāng)開發(fā)結(jié)束后,完善的項(xiàng)目代碼需要在一個(gè)高效穩(wěn)定的環(huán)境中運(yùn)行,這時(shí)可以使用uWSGI

  • uWSGI是WSGI的一種,它可以讓Django、Flask等開發(fā)的web站點(diǎn)運(yùn)行其中.

  • 安裝uWSGI
    $ sudo pip3 install uwsgi

  • 配置uWSGI

    # file: 項(xiàng)目文件夾/uwsgi.ini  # 如: mysite1/uwsgi.ini
    [uwsgi]
    # 套接字方式的 IP地址:端口號(hào)
    # socket=127.0.0.1:8000
    # Http通信方式的 IP地址:端口號(hào)
    http=127.0.0.1:8000
    # 項(xiàng)目當(dāng)前工作目錄
    chdir=/home/weimz/my_django_project ... 這里需要換為項(xiàng)目地址
    # 項(xiàng)目中wsgi.py文件的目錄,相對(duì)于當(dāng)前工作目錄
    wsgi-file=my_django_project/wsgi.py
    # 進(jìn)程個(gè)數(shù)
    process=4
    # 每個(gè)進(jìn)程的線程個(gè)數(shù)
    threads=2
    # 服務(wù)的pid記錄文件
    pidfile=uwsgi.pid
    # 服務(wù)的目志文件位置
    daemonize=uwsgi.log
    
  • uWSGI的運(yùn)行管理

    • 啟動(dòng) uwsgi
      $ cd 項(xiàng)目文件夾
      $ sudo uwsgi --ini 項(xiàng)目文件夾/uwsgi.ini
      
    • 停止 uwsgi
      $ cd 項(xiàng)目文件夾
      $ sudo uwsgi --stop uwsgi.pid
      
    • 說(shuō)明:
      • 當(dāng)uwsgi 啟動(dòng)后,當(dāng)前django項(xiàng)目的程序已變成后臺(tái)守護(hù)進(jìn)程,在關(guān)閉當(dāng)前終端時(shí)此進(jìn)程也不會(huì)停止。
  • 測(cè)試:

    • 在瀏覽器端輸入http://127.0.0.1:8000 進(jìn)行測(cè)試
    • 注意,此時(shí)端口號(hào)為8000

nginx 反向代理配置

  • Nginx是輕量級(jí)的高性能Web服務(wù)器,提供了諸如HTTP代理和反向代理、負(fù)載均衡、緩存等一系列重要特性,在實(shí)踐之中使用廣泛。

  • C語(yǔ)言編寫,執(zhí)行效率高

  • nginx 作用

    • 負(fù)載均衡, 多臺(tái)服務(wù)器輪流處理請(qǐng)求
    • 反向代理
  • 原理:

    • 客戶端請(qǐng)求nginx,再由nginx 請(qǐng)求 uwsgi, 運(yùn)行django下的python代碼
  • ubuntu 下 nginx 安裝
    $ sudo apt install nginx

  • nginx 配置

    • 修改nginx 的配置文件 /etc/nginx/sites-available/default
    # 在server節(jié)點(diǎn)下添加新的location項(xiàng),指向uwsgi的ip與端口。
    server {
        ...
        location / {
            uwsgi_pass 127.0.0.1:8000;  # 重定向到127.0.0.1的8000端口
            include /etc/nginx/uwsgi_params; # 將所有的參數(shù)轉(zhuǎn)到uwsgi下
        }
        ...
    }
    
  • 啟動(dòng) nginx

    • $ sudo /etc/init.d/nginx start
    • $ sudo service nginx restart
  • 查看nginx進(jìn)程

    • $ ps aux | grep nginx
    • $ sudo /etc/init.d/nginx status
    • $ sudo service nginx status
  • 停止nginx

    • $ sudo /etc/init.d/nginx stop
    • $ sudo service nginx stop
  • 重啟nginx

    • $ sudo /etc/init.d/nginx restart
    • $ sudo service nginx restart
  • 修改uWSGI配置

    • 修改項(xiàng)目文件夾/uwsgi.ini下的Http通信方式改為socket通信方式,如:
    [uwsgi]
    # 去掉如下
    # http=127.0.0.1:8000
    # 改為
    socket=127.0.0.1:8000
    
    • 重啟uWSGI服務(wù)
    $ sudo uwsgi --stop uwsgi.pid
    $ sudo uwsgi --ini 項(xiàng)目文件夾/uwsgi.ini
    
    
  • 測(cè)試:

    • 在瀏覽器端輸入http://127.0.0.1 進(jìn)行測(cè)試
    • 注意,此時(shí)端口號(hào)為80(nginx默認(rèn)值)

nginx 配置靜態(tài)文件路徑

  • 解決靜態(tài)路徑問(wèn)題
    # file : /etc/nginx/sites-available/default
    # 新添加location /static 路由配置,重定向到指定的絕對(duì)路徑
    server {
        ...
        location /static {
            # root static文件夾所在的絕對(duì)路徑,如:
            root /home/weimz/my_django_project; # 重定向/static請(qǐng)求的路徑,這里改為你項(xiàng)目的文件夾
        }
        ...
    }
    
  • 修改配置文件后需要重新啟動(dòng) nginx 服務(wù)

404 界面

  • 在模板文件夾內(nèi)添加 404.html 模版,當(dāng)響應(yīng)返回HttpResponseNotFound 或 raise Http404時(shí)將會(huì)被顯示
  • 404.html 僅在發(fā)布版中(即setting.py 中的 DEBUG=False時(shí)) 才起作用
  • 當(dāng)向應(yīng)處理函數(shù)觸發(fā)Http404異常時(shí)就會(huì)跳轉(zhuǎn)到404界面
    from django.http import Http404
    def xxx_view(request):
        raise Http404  # 直接返回404
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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