1. 程式人生 > 實用技巧 >flask做web基礎

flask做web基礎

flask是python的一個web微框架 做演示demo/或者簡單網頁工具十分方便

安裝flask:pip install flask

用來做一個正式網站還是需要配置良好的目錄結構

flask-demo/
  ├ run.py           # 應用啟動程式
  ├ config.py        # 環境配置
  ├ requirements.txt # 列出應用程式依賴的所有Python包
  ├ tests/           # 測試程式碼包
  │   ├ __init__.py 
  │   └ test_*.py    # 測試用例
  └ myapp/
	  ├ admin/       # 藍圖目錄
	  ├ static/
	  │   ├ css/     # css檔案目錄
	  │   ├ img/     # 圖片檔案目錄
	  │   └ js/      # js檔案目錄
	  ├ templates/   # 模板檔案目錄
	  ├ __init__.py    
	  ├ forms.py     # 存放所有表單,如果多,將其變為一個包
	  ├ models.py    # 存放所有資料模型,如果多,將其變為一個包
	  └ views.py     # 存放所有檢視函式,如果多,將其變為一個包

最簡單測試:test.py

python test.py 後,瀏覽器輸入localhost:5000就能看到網頁顯示Hello world。 或者輸入:127.0.0.1:5000

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
	return 'Hello World'
if __name__ == '__main__':
	app.debug = True # 設定除錯模式,生產模式的時候要關掉debug
	app.run()

Jinja2是一個廣泛應用的模板引擎,可以很方便的把資料嵌入到網頁問價中

from  flask import  Flask
from  flask import  render_template
app  =  Flask(__name__)
@app.route('/hello')
@app.route('/hello/<name>')
def  hello(name=None):
	#渲染hello.html模板,把name資料傳入進去
	return  render_template('hello.html',  name=name)
if  __name__  ==  '__main__':
	app.run(host='0.0.0.0',  debug=True)

#模版檔案:hello.html ”http://localhost:5000/hello/world”

<!doctype html>
<title>Hello Sample</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello World!</h1>
{%  endif  %}

#模板繼承 #father.html

<!doctype html>
<title>Hello Sample</title>
<link rel="stylesheet"  type="text/css"  href="{{ url_for('static', filename='style.css') }}">
<div class="page">
	{% block body %}
	{% endblock %}
</div>

#繼承上面模板

{%  extends  "father.html"  %}
{%  block  body  %}
{%  if  name  %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello World!</h1>
{%  endif  %}
{%  endblock  %}

會話session 記錄已登入資訊,避免重複進入登入頁面

from flask import Flask,url_for,request,render_template,redirect,session
@app.route('/login', methods=['POST', 'GET'])
def login():
	if request.method == 'POST':
		if request.form['user'] == 'admin':
			session['user'] = request.form['user']
			return 'Admin login successfully!'
		else:
			return 'No such user!'
	if 'user' in session:
		return 'Hello %s!' % session['user']
	else:
		title = request.args.get('title', 'Default')
		return render_template('login.html', title=title)
@app.route('/logout')
def logout():
	session.pop('user', None)
	return redirect(url_for('login'))
app.secret_key = '123456'
if __name__ == "__main__":
	app.run(debug=True)

使用Cookie

from flask import Flask,url_for,request,render_template,redirect,session,make_response
import time
@app.route('/login', methods=['POST', 'GET'])
def login():
	response = None
	if request.method == 'POST':
		if request.form['user'] == 'admin':
			session['user'] = request.form['user']
			response = make_response('Admin login successfully!')
			#設定Cookie,儲存在瀏覽器中,第三個引數max_age設定有效期(秒),不設定則瀏覽器關閉後失效
			response.set_cookie('login_time', time.strftime('%Y-%m-%d %H:%M:%S'))
		...
	else:
		if 'user' in session:
			#”request.cookies”物件就是一個儲存了瀏覽器Cookie的字典,使用其”get()”函式就可以獲取相應的鍵值。
			login_time = request.cookies.get('login_time')
			response = make_response('Hello %s, you logged in on %s' % (session['user'], login_time))
		...
	return response
app.secret_key = '123456' #設定祕鑰,最好使用隨機
if __name__ == "__main__":
	app.run(debug=True)

錯誤處理

from flask import Flask,abort
app = Flask(__name__)
@app.route('/error')
def error():
	abort(404) #直接退出
@app.errorhandler(404)
def page_not_found(error):
	return render_template('404.html'), 404 #返回重寫的錯誤頁面
if __name__ == "__main__":
	app.run(debug=True)

URL重定向:

#不帶/時,Flask會自動重定向到正確地址。

@app.route('/projects/')
def projects():
	return 'The project page'
#末尾帶上/後Flask會直接報404 NOT FOUND錯誤
@app.route('/about')
def about():
	return 'The about page'
---------------------------------------------
from flask import session, redirect
@app.route('/')
def index():
	if 'user' in session:
		return 'Hello %s!' % session['user']
	else:
		#redirect()”函式當客戶端瀏覽某個網址時,將其導向到另一個網址
		#“redirect()”的第二個引數時HTTP狀態碼,可取的值有301, 302, 303, 305和307,預設即302
		return redirect(url_for('login'), 302)

#上傳檔案 #werkzeug 判斷檔名是否安全 pip install werkzeug #服務端:

from flask import Flask, request  
from werkzeug.utils import secure_filename  
import os

app = Flask(__name__)  
#配置資訊 上傳目錄 
app.config['UPLOAD_FOLDER'] = 'static/uploads/'
#控制上傳檔案的大小
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB
#上傳檔案格式,字尾名
app.config['ALLOWED_EXTENSIONS'] = set(['png', 'jpg', 'jpeg', 'gif'])

# For a given file, return whether it's an allowed type or not
def allowed_file(filename):  
	return '.' in filename and 
		   filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']

@app.route('/')
def hello_world():  
	return 'hello world'

@app.route('/upload', methods=['POST'])
def upload():  
	upload_file = request.files['image01']#圖片以"image01"標識
	file_content = request.files['image01'].stream.read()#獲取上傳檔案的內容
	if upload_file and allowed_file(upload_file.filename):
		filename = secure_filename(upload_file.filename)
		#路徑
		upload_file.save(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
		return 'hello, '+request.form.get('name', 'little apple')+'. success'
	else:
		return 'hello, '+request.form.get('name', 'little apple')+'. failed'

if __name__ == '__main__':  
	app.run(debug=True)

客戶端

import requests
#當前目錄下的 01.jpg上傳到伺服器
files = {'image01': open('01.jpg', 'rb')}  
user_info = {'name': 'letian'}  
r = requests.post("http://127.0.0.1:5000/upload", data=user_info, files=files)


#coding=utf-8
from flask import Flask
from flask import request
app = Flask(__name__)

#路由 是指url/register只接受POST方法。也可以根據需要修改methods引數

@app.route("/login", methods=["GET", "POST"])
def hello_str():
	if request.method == "POST":
		print(request.headers) #請求頭
		#多種接收資料方法
		username = request.form['username']
		username = request.form.get("username",type = str,default="admin") #獲取表單資料
		#對應請求requests.post(url, json.dumps(params)) as_text=True 變成Unicode 使用 json.loads()轉換字典
		params = request.get_data(as_text=True) 
		params = request.get_json()
		params = request.data
	elif request.method == "GET":

		username = request.args.get("username") #獲取get請求引數
		username = request.values.get("username") #獲取所有有請求引數
	return redirect(url_for('home',username=request.form['username']))

@app.route('/home')
def home():
	return render_template('home.html', username=request.args.get('username'))

if __name__ == "__main__":
	#要控制上產檔案的大小,可以設定請求實體的大小,檔案
	app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB
	app.debug = True
	app.run('0.0.0.0',80)

#post 請求

import requests, json user_info = {'name': 'letian'}
headers = {'content-type': 'application/json'}
r = requests.post("http://127.0.0.1:5000/json", data=json.dumps(user_info), headers=headers)
print r.headers
print r.json()

構建相應 自己設定相應引數返回
from flask import Flask,url_for,request,render_template,redirect,session,make_response
@app.route('/login', methods=['POST', 'GET'])
def login():
	if request.method == 'POST':
		...
	if 'user' in session:
		...
	else:
		title = request.args.get('title', 'Default')
		response = make_response(render_template('login.html', title=title), 200)
		response.headers['key'] = 'value'
		return response
if __name__ == "__main__":
	app.run(debug=True)

request相關屬性

form        接收POST/PUT請求資料,MultiDict
arges       MultiDict如searchword = request.args.get('key', '')
values      可以代替form和args
cookies     請求的cookies,型別是dict
headers     請求頭,型別是dict
data        包含請求的資料,轉為字串,處理不了mimetype
files       MultiDict,帶有POST/PUT請求上傳的檔案
environ     WSGI環境配置
method      請求方法,如GET,POST
path        獲取請求檔案路徑
base_url    獲取域名與請求檔案路徑
url         獲取全部url
url_root    獲取域名
blueprint   藍圖名字
endpoint    endpoint匹配請求
json        如果mimetype是application/json,會解析json,不是則返回None,可替代get_json()
max_content_length  返回MAX_CONTENT_LENGTH的配置鍵

view_args = None	一個匹配請求的view引數的字典,當匹配的時候發生異常,會返回None。
get_json(force=False, silent=False, cache=True)

下面的應該用不到,搬運過來
on_json_loading_failed(e)
module      如果請求是傳送到一個實際的模組,則該引數返回當前模組的名稱。這是棄用的功能,使用blueprints替代。
routing_exception = None        如果匹配URL失敗,這個異常將會/已經丟擲作為請求處理的一部分。這通常用於NotFound異常或類似的情況。
url_rule = None     內部規則匹配請求的URL。這可用於在URL之前/之後檢查方法是否允許(request.url_rule.methods) 等等。
預設情況下,在處理請求函式中寫下print('request.url_rule.methods', request.url_rule.methods)
會列印:
request.url_rule.methods {‘GET’, ‘OPTIONS’, ‘HEAD’}