Flask簡介:html
Flask是一個Python編寫的Web 微框架,讓咱們可使用Python語言快速實現一個網站或Web服務,在介紹Flask以前首先來聊下它和Django的聯繫以及區別,django個大而全的web框架,它內置許多模塊,flask是一個小而精的輕量級框架,Django功能大而全,Flask只包含基本的配置 Django的一站式解決的思路,能讓開發者不用在開發以前就在選擇應用的基礎設施上花費大量時間。Django有模板,表單,路由,認證,基本的數據庫管理等等內建功能。與之相反,Flask只是一個內核,默認依賴於兩個外部庫: Jinja2 模板引擎和 Werkzeug WSGI 工具集,其餘不少功能都是以擴展的形式進行嵌入使用,相比於其餘Web框架例如Django,更加靈活也更加簡潔,以下幾行代碼就能夠寫出一個小程序:前端
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello Flask!' if __name__ == '__main__': app.run()
接下來咱們按照執行順序來了解下Flaskhtml5
配置文件python
app.config.from_object("settings.DevelopmentConfig")
路由
路由經過使用Flask的app.route
裝飾器來設置web
動態路由(url傳參)ajax
@app.route('/user/<username>') def show_user_profile(username): # show the user profile for that user return 'User %s' % username @app.route('/post/<int:post_id>') def show_post(post_id): # show the post with the given id, the id is an integer return 'Post %d' % post_id
若是但願獲取/article/1
這樣的路徑參數,就須要使用路徑變量。路徑變量的語法是/path/<converter:varname>
。在路徑變量前還可使用可選的轉換器,有如下幾種轉換器。redis
轉換器 | 做用 |
---|---|
string | 默認選項,接受除了斜槓以外的字符串 |
int | 接受整數 |
float | 接受浮點數 |
path | 和string相似,不過能夠接受帶斜槓的字符串 |
any | 匹配任何一種轉換器 |
uuid | 接受UUID字符串 |
HTTP方法sql
若是須要處理具體的HTTP方法,在Flask中也很容易,使用route
裝飾器的methods
參數設置便可。數據庫
- GET 將未經加密的信息發送的服務器. 是最通用的方法.
- HEAD 該方法除了服務端不返回響應內容只返回頭信息以外, 同GET是同樣的.
- POST 用於向服務器發送HTML表單數據. POST請求不會被緩存.
- PUT 將URL所指示的資源用上傳的內容替換.
- DELETE 將URL所指示的資源刪除.
from flask import request,render_template @app.route('/login', methods=['GET', 'POST']) #若是不加methods,Flask路由默認處理的是GET請求 def login(): if request.method == 'POST': do_the_login() else: return render_template('xxx.html')
url_for 和 endpointdjango
from flask import Flask,url_for app=Flask(__name__) @app.route('/<path:url>',endpoint='XXX') #endpoint默認爲函數名 def demo(url): print(url_for('XXX',url=url)) #若是設置了url參數,url_for(別名,加參數) return 'Hello World' if __name__ == '__main__': app.run()
處理請求
Request 對象
Request 對象是一個全局對象,利用它的屬性和方法,咱們能夠方便的獲取從頁面傳遞過來的參數。
request.method | 獲取請求方法 |
request.form | 獲取POST類型的表單提交的數據和ajax請求的數據 |
request.args | 獲取get請求參數 |
request.values | 獲取GET和POST請求攜帶的全部參數(GET/POST通用) |
request.cookies | 獲取cookies信息 |
request.headers | 獲取請求頭信息 |
request.path | 獲取cookies信息 |
request.full_path | 獲取獲取用戶訪問的完整url地址+參數 例如(/index/?page=1) |
request.url | 獲取完整路徑 |
request.base_url | 獲取訪問url地址(不獲取參數),例如 http://127.0.0.1:5000/; |
request.files | 獲取用戶上傳的文件 |
響應處理
- 返回字符串 ----return 「asdf」
- 返回模板 ----return render_template('xxx.html')
- 返回重定向 ----return redirect(' /')
- 返回字典 ----jsonify({'k1':'v1'})
默認的錯誤頁面是一個空頁面,若是須要自定義錯誤頁面,可使用errorhandler
裝飾器。
from flask import render_template @app.errorhandler(404) def page_not_found(error): return render_template('page_not_found.html'), 404
咱們也能夠本身決定如何設置響應對象,方法也很簡單,使用make_response
函數便可。
@app.errorhandler(404) def not_found(error): resp = make_response(render_template('error.html'), 404) resp.headers['X-Something'] = 'A value' return resp
session
咱們可使用全局對象session
來管理用戶會話。Sesison 是創建在 Cookie 技術上的,不過在 Flask 中,咱們還能夠爲 Session 指定密鑰,這樣存儲在 Cookie 中的信息就會被加密,從而更加安全。
from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) app.secret_key = 'qwertyuiop' @app.route('/') def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return ''' <form method="post"> <p><input type=text name=username> <p><input type=submit value=Login> </form> ''' @app.route('/logout') def logout(): # remove the username from the session if it's there session.pop('username', None) return redirect(url_for('index'))
Blueprint
- 目錄結構劃分
- 前綴
- 特殊裝飾
- 某一類url添加前綴url_prefix
@h.route('',methods=[],url_prefix='')
- 給一類url添加before_request
特殊裝飾器
app.before_request 修飾器在開發中用處很是大,好比判斷某個ip是否有惡意訪問行爲,從而進行攔截等操做。
app.after_request 修飾器是在用戶請求獲得函數響應後被執行,不過須要注意的是這個執行是在函數返回數據前被調用,即請求已經被app.route修飾的函數響應過了,已經造成了response,但還未返回給用戶的時候,調用的。
from flask import Flask, Request, render_template app = Flask(__name__, template_folder='templates') app.debug = True @app.before_first_request #第1個請求到來執行 def before_first_request(): print('before_first_request') @app.before_request #在進入視圖前執行 def before_request():
if request.path=='/login':
return None if session['user']:
return None
return redirect('/login')
@app.errorhandler(404) def page_not_found(error): return 'This page does not exist', 404 @app.route('/index') def index(): return "Hello World" @app.after_request #視圖以後執行 def after_request1(response): print('after_request1', response) return response @app.after_request #先執行 after_request2 def after_request2(response): print('after_request2', response) return response if __name__ == '__main__': app.run()
模板
使用方式和Django的模板渲染相似:{{ }} 和 {% %}。
基本方法不太同樣,函數須要加括號執行,相似於python的語法:
- {{ dict.get() }} 或 {{ dict["key"] }}
- {{ list[0] }}
- {% for 循環 %} {% endfor %}
- {% if 判斷 %} {% endif %}
還能夠自定義全局函數,在模板中使用:
@app.template_global() def sum(a1, a2): return a1 + a2 # 模板中使用{{ sum(2, 3) }} # 相似的 @app.template_filter() def sum(a1, a2, a3): return a1 + a2 + a3 # 調用方式不一樣{{ 1|sum(2,3) }}
模板繼承:
{% extends "base.html"%} {% block content %} 自定義內容 {% endblock %} {% include "組件.html" %}
定義宏:
{% macro input(name, type='text', value=' ') %} <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> {% endmacro %} # 使用 <form> {{ input('username') }} {{ input('password', type="password") }} {{ input(' ', type="submit", value="提交") }} </form>
安全:
# 前端 {{ data|safe }} # 後端 from flask import Markup data = Markup(data)
Flash
flask中暫時儲存數據的一個方式
from flask import flash, get_flashed_messages # 儲存數據 flash("臨時數據", "name") # 獲取數據, 經過pop獲取並移除 msg = get_flashed_messages(category_filter=["name"])
wtforms
安裝:pip3 install wtforms
用戶登陸註冊示例
1. 用戶登陸
當用戶登陸時候,須要對用戶提交的用戶名和密碼進行多種格式校驗。如:
密碼不能爲空;密碼長度必須大於12;密碼必須包含 字母、數字、特殊字符等(自定義正則);
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder='templates') app.debug = True class LoginForm(Form): name = simple.StringField( label='用戶名', validators=[ validators.DataRequired(message='用戶名不能爲空.'), validators.Length(min=6, max=18, message='用戶名長度必須大於%(min)d且小於%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能爲空.'), validators.Length(min=8, message='用戶名長度必須大於%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", message='密碼至少8個字符,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': form = LoginForm() return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print('用戶提交數據經過格式驗證,提交的值爲:', form.data) else: print(form.errors) return render_template('login.html', form=form) if __name__ == '__main__': app.run()
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder='templates') app.debug = True class LoginForm(Form): name = simple.StringField( label='用戶名', validators=[ validators.DataRequired(message='用戶名不能爲空.'), validators.Length(min=6, max=18, message='用戶名長度必須大於%(min)d且小於%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能爲空.'), validators.Length(min=8, message='用戶名長度必須大於%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", message='密碼至少8個字符,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': form = LoginForm() return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print('用戶提交數據經過格式驗證,提交的值爲:', form.data) else: print(form.errors) return render_template('login.html', form=form) if __name__ == '__main__': app.run()
2.註冊
from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder='templates') app.debug = True class RegisterForm(Form): name = simple.StringField( label='用戶名', validators=[ validators.DataRequired() ], widget=widgets.TextInput(), render_kw={'class': 'form-control'}, default='alex' ) pwd = simple.PasswordField( label='密碼', validators=[ validators.DataRequired(message='密碼不能爲空.') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) pwd_confirm = simple.PasswordField( label='重複密碼', validators=[ validators.DataRequired(message='重複密碼不能爲空.'), validators.EqualTo('pwd', message="兩次密碼輸入不一致") ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) email = html5.EmailField( label='郵箱', validators=[ validators.DataRequired(message='郵箱不能爲空.'), validators.Email(message='郵箱格式錯誤') ], widget=widgets.TextInput(input_type='email'), render_kw={'class': 'form-control'} ) gender = core.RadioField( label='性別', choices=( (1, '男'), (2, '女'), ), coerce=int ) city = core.SelectField( label='城市', choices=( ('bj', '北京'), ('sh', '上海'), ) ) hobby = core.SelectMultipleField( label='愛好', choices=( (1, '籃球'), (2, '足球'), ), coerce=int ) favor = core.SelectMultipleField( label='喜愛', choices=( (1, '籃球'), (2, '足球'), ), widget=widgets.ListWidget(prefix_label=False), option_widget=widgets.CheckboxInput(), coerce=int, default=[1, 2] ) def __init__(self, *args, **kwargs): super(RegisterForm, self).__init__(*args, **kwargs) self.favor.choices = ((1, '籃球'), (2, '足球'), (3, '羽毛球')) def validate_pwd_confirm(self, field): #局部鉤子,全局鉤子爲 def validate() """ 自定義pwd_confirm字段規則,例:與pwd字段是否一致 :param field: :return: """ # 最開始初始化時,self.data中已經有全部的值 if field.data != self.data['pwd']: # raise validators.ValidationError("密碼不一致") # 繼續後續驗證 raise validators.StopValidation("密碼不一致") # 再也不繼續後續驗證 @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'GET': form = RegisterForm(data={'gender': 1}) return render_template('register.html', form=form) else: form = RegisterForm(formdata=request.form) if form.validate(): print('用戶提交數據經過格式驗證,提交的值爲:', form.data) else: print(form.errors) return render_template('register.html', form=form) if __name__ == '__main__': app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用戶註冊</h1> <form method="post" novalidate style="padding:0 50px"> {% for item in form %} <p>{{item.label}}: {{item}} {{item.errors[0] }}</p> {% endfor %} <input type="submit" value="提交"> </form> </body> </html>
flask-session組件
在app的__init__中
from flask import Flask from flask_session import Session # 第一步:導入並實例化SQLAlchemy from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() from .views.account import ac from .views.user import us from .models import * def create_app(): app = Flask(__name__) app.config.from_object('settings.Config') app.register_blueprint(ac) app.register_blueprint(us) # Flask-Session: 第一步示例Session # Session(app) # 第三步:依賴app中的配置文件 db.init_app(app) return app
在settings中
class Config(object):
#配置
SESSION_TYPE = 'redis' SESSION_REDIS = Redis(host='192.168.0.94', port='6379')
SECRET_KEY='QWERT' #使用session,必須配置secret_key 不然會報錯