天天看點

Flask入門檔案上傳郵件發送(八)

1 視圖傳遞多個參數

(1) 普通傳參 : 關鍵字參數傳遞

return render_template('模闆名稱.html',arg1=val1,arg2=val2...)           

(2) 字典傳參 : 以字典的形式傳遞

dict = {
    key1:value1,
    key2:value2,
    ....
}
return render_template('模闆名稱.html',dict)           

(3) 全局變量g傳遞

視圖中:

@app.route('/test')
def test():
    g.name = '張三'
    g.sex = '男'
    return render_template('test.html')           

模闆中

<h2>{{ g.name }}</h2>
 <h2>{{ g.sex }}</h2>           

(4) 傳遞全部的本地變量給template,使用**locals(),直接擷取變量值

@app.route('/test')
def test():
    name = '張三'
    sex = '男'
    return render_template('test.html',**locals())           

test.html中

<h2>{{ name }}</h2>
<h2>{{ sex }}</h2>           

2 錯誤頁面定制

#制定捕獲404和500的錯誤頁面
@app.errorhandler(404)
def page_not_found(e):
    return render_template('error.html',error=e,code=404)

@app.errorhandler(500)
def page_not_found(e):  #接受參數e,并傳給錯誤error
    return render_template('error.html',error=e,code=500)           

指定錯誤頁面:隻需要一個錯誤模闆頁面即可

{% extends 'common/boot_base.html' %}
{% block title %}
{{ code }}  #标題顯示500
{% endblock %}
{% block page_content %}
    <div class="alert alert-danger" role="alert">{{ error }}  #顯示錯誤頁面資訊
</div>
{% endblock %}           

3 檔案上傳

(1) 靜态資源的加載

{{ url_for('static',filename='img/mei.jpg') }} 
{{ url_for('static',filename='css/style.css') }} 
{{ url_for('static',filename='js/mei.js') }} 

#注:static是内置的視圖函數,我們通過其找到路由           

(2) 原生檔案上傳

模闆檔案

{% if newName %}  #newName非空 圖檔名傳入
    <img src='{{ url_for("static",filename=newName) }}' alt=''>
{% endif %}
#視圖函數upLoad  
<form action="{{ url_for('upLoad') }}" enctype='multipart/form-data' method='post'>
    <input type='file' name='file'>
    <p><input type='submit' value='submit'></p>
</form>           

主檔案manage.py

from flask import Flask,render_template,request
from flask_script import Manager
from flask_bootstrap import Bootstrap
import os
from PIL import Image  #python圖檔處理庫

app = Flask(__name__)
#允許上傳的字尾名,放在配置檔案
app.config['ALLOWED_EXTENSIONS'] = ['.jpg','.jpeg','.png','.gif']
#上傳檔案的大小
app.config['MAX_CONTENT_LENGTH'] = 1024*1024*60
#配置檔案上傳的路徑
app.config['UPLOAD_FOLDER'] = os.getcwd() + '/static'

#綁定bootstrap
bootstrap = Bootstrap(app)
manager = Manager(app)

@app.route('/')
def index():
    return render_template('index.html')

#生成随機圖檔名稱的函數
def new_name(shuffix,length=32):
    import string,random
    myStr = string.ascii_letters + '0123456789'
    newName = ''.join(random.choice(myStr) for i in range(length))
    return newName+shuffix

#定義判斷字尾是否可用函數,傳回true/false
def allowed_file(shuffix):
    return shuffix in app.config['ALLOWED_EXTENSIONS']

@app.route('/upload',methods=['GET','POST'])
def upload():
    img_name = None
    if request.method == 'POST':
        file = request.files.get('file')
        #擷取上傳檔案的名稱
        filename = file.filename
        #分割路徑,傳回路徑名和檔案擴充名的元組
        shuffix = os.path.splitext(filename)[-1]
        if allowed_file(shuffix):
            #為真則生成随機名稱
            newName = new_name(shuffix)
            img_name = newName
            #拼湊完整的路徑
            newPath = os.path.join(app.config['UPLOAD_FOLDER'],newName)
            file.save(newPath)

            #處理圖檔的縮放
            img = Image.open(newPath)
            #重新設定大小與尺寸
            img.thumbnail((200,200))
            img.save(newName)
     #跳轉上傳頁面并傳回newName
     return render_template('upload.html',newName=img_name)           

4 flask-uploads擴充庫

安裝

pip3 install flask-uploads           

類UploadSet : 檔案上傳配置集合,包含三個參數:

name:檔案上傳配置集合的名稱,預設files

extensions:上傳檔案類型,預設DEFAULTS = TEXT + DOCUMENTS + IMAGES + DATA

default_dest:上傳檔案的預設存儲路徑,我們可以通過app.config[‘UPLOADS_DEFAULT_DEST’]來指定

方法 : configure_uploads

應用配置好之後,調用此方法,掃描上傳配置選項并儲存到我們的應用中,注冊上傳子產品。

下面我們來看下 (flask-uploads庫 + flask-wtf 庫) 的寫法

{% extends 'common/base.html' %}  #繼承
{% block title %}
    首頁
{% endblock %}
{% import 'bootstrap/wtf.html' as wtf %}  #導入
{% block page_content %}
    <img src="{{ url_for('static',filename=newName) }}" alt="">
    {{ wtf.quick_form(form) }}   #快速渲染
{% endblock %}           

主啟動檔案

from flask import Flask,render_template,request
from flask_script import Manager
from flask_bootstrap import Bootstrap
import os
from flask_uploads import UploadSet,IMAGES,configure_uploads,patch_request_class
#導入庫中驗證的字段類
from flask_wtf import FlaskForm
from wtforms import FileField,SubmitField
from flask_wtf.file import FileAllowed,FileRequired

app = Flask(__name__)
#允許上傳的字尾
app.config['SECRET_KEY'] = 'image'
app.config['MAX_CONTENT_LENGTH'] = 1024*1024*64 #64兆
#配置檔案上傳的路徑
app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()+'/static/upload'

#執行個體化一個file對象  photos與PHOTOS要對應
file = UploadSet('photos',IMAGES)
#将 app 的 config 配置注冊到 UploadSet 執行個體 file
configure_uploads(app,file)
#限制上傳檔案的大小   size=None不采用預設size=64*1024*1024
patch_request_class(app,size=None)

bootstrap = Bootstrap(app)
manager = Manager(app)

class File(FlaskForm):
    file = FileField('檔案上傳',validators=[FileRequired(message='您還沒有選擇檔案'),FileAllowed(file,message='隻能上擦圖檔')])
    submit = SubmitField('上傳')

#生成随機圖檔名稱的函數
def new_name(shuffix,length=32):
    import string, random
    myStr = string.ascii_letters + '0123456789'
    newName = ''.join(random.choice(myStr) for i in range(length))
    return newName+shuffix

@app.route('/upload',methods=['GET','POST'])
def upload():
    form = File()
    img_url = None
    #驗證資料
    if form.validate_on_submit():
        shuffix = os.path.splitext(form.file.data.filename)[-1]
        newName = new_name(shuffix=shuffix)
        file.save(form.file.data,name=newName)
        img_url = file.url(newName)
    return  render_template('boot_upload.html',newName=img_url,form=form)

if __name__ == '__main__':
    manager.run()           

注意事項:

1 将app的config配置注冊到 UploadSet 執行個體file configure_uploads(app,file)

2 限制上傳檔案的大小 patch_request_class(app,size=None)

3 file = UploadSet(‘photos’,IMAGES) 執行個體化file對象繼承類中save() url() 内置方法

4 form = File() File類繼承自FlaskForm 可以利用flask-uploads庫進行驗證 , 采用類File取代原生的Form表單通路通過 :

執行個體化form對象.字段名.data 通路字段對象

執行個體化form對象.字段名.data.屬性名 通路字段對象對應的屬性