flask基礎之一

flask基礎之一

hello world

#從flask這個包中導入Flask這個類
#Flask這個類是項目的核心,之後的不少操做都是基於這個類的對象
#註冊url,註冊藍圖都是這個類的對象
from flask import Flask
#建立一個Flask對象,傳遞__name__這個參數進去
#__name__這個參數的做用:
# 1.規定模板和靜態資源的路徑
# 2.之後的一些Flask插件,好比Flask_migrate,Flask_SQLAlchemy報錯的話,哪麼Flask就會經過這個參數找到具體的報錯位置
app = Flask(__name__)
# @app.route()是一個裝飾器,將對應的「/」路徑應用到hello_world()這個函數上面
# 在訪問「/」的時候在頁面上返回Hello World
@app.route('/')
def hello_world():
    return 'Hello World!'
# 若是做爲一個主文件運行,哪麼執行app.run()方法,也就是啓動這個網站
if __name__ == '__main__':
    app.run()

debug模式

  • 爲何要開啓DEBUG模式?
  • 若是開啓了debug模式,name代碼在調試過程當中出現了異常,在瀏覽器頁面中能夠看到具體的報錯信息,以及具體的錯誤代碼位置,方便開發者調試。
  • 若是flask開啓了debug模式,name之後再python中修改任何代碼,只要在pycharm中使用ctrl+s便可保存重載,不須要手動去重載程序
  • 如何配置debug模式:

app.run()php

app.run(debug=True)

app.debughtml

app.debug = True

配置信息方式(使用參數形式的方式)前端

app.config.update[DEBUG=True]
#其實也就是update了config字典

經過配置文件的形式python

- 建立一個config.py的配置文件,寫入
DEBUG = True
- 而後在你的app.py文件中寫入
app.config.from_object(config) #便可讀取配置文件中的DEBUG=True

debug PIN碼正則表達式

D:\MyDevSoftInstallDir\Python3\python3.exe D:/myflask/base/base.py
* Restarting with stat
* Debugger is active!
* Debugger PIN: 177-952-649
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

而後在頁面上調試代碼的時候用到。
也是爲了安全考慮。json

配置文件兩種方式詳解

  • 第一種方式:

在項目主路徑下建立config.pyflask

DEBUG=True

而後在主項目裏面去讀取config.py裏面的配置:瀏覽器

from flask import Flask
import config
app = Flask(__name__)
app.config.from_object(config)
  • 第二種方式:直接讀取文件的形式,也能夠是普通的txt文件形式;這種方式不須要直接import config

在項目主路徑下建立config.py安全

DEBUG=True

而後在主項目裏面去讀取config.py裏面的配置:bash

from flask import Flask
app = Flask(__name__)
app.config.from_pyfile('config.py',silent=True) #靜默模式加載配置文件(找不到配置文件不報錯),文件的後綴名不可少

url與視圖函數的映射

  • 傳遞參數:
傳遞參數的語法是 /<參數類型:參數名稱>/,而後在視圖函數中也要定義同名的參數
  • 參數的數據類型
  • string:只接受字符串,沒有任何「/或者」的文本
  • int:只接受整數
  • float:只接受浮點數,整數都不行哈
  • path:和string相似,可是接受斜槓
  • uuid:只有接受符合uuid的字符赤岸,通常用做表的主鍵
  • any:能夠指定多種路徑

接收用戶傳遞參數的方式:

  • 使用path的方式(將參數嵌入到路徑中)
  • 使用查詢字符串的形式 (也就是經過?key=value的形式傳遞的,只能經過request.args.get的方式來獲取)

若是頁面想要作SEO優化的話,那麼推薦使用path的形式,反之就是查詢字符串的形式
練習

from flask import Flask,request
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello World!'
@app.route('/list/')
def article_list():
    return 'article list!'
@app.route('/p1/<article_id1>')
def article_detail(article_id1):
    return "請求的文章是:%s" %article_id1
@app.route('/p2/<string:article_id2>')
def article_detail2(article_id2):
    return "請求的文章是:%s" %article_id2
@app.route('/p3/<int:article_id3>')
def article_detail3(article_id3):
    return "請求的文章是:%s" %article_id3
@app.route('/p4/<path:article_id4>')
def article_detail4(article_id4):
    return "請求的文章是:%s" %article_id4
# import uuid
# print(uuid.uuid4())
@app.route('/p5/<uuid:article_id5>') #數據的惟一性,長度較長,有損效率(通常在用戶表中使用)6a9221f6-afea-424a-a324-8ceaa5bdfc98
def article_detail5(article_id5):
    return "請求的文章是:%s" %article_id5
@app.route('/p6/<any(blog,user):url_path>/<id>/')
def detail(url_path,id):
    if url_path == "blog":
        return "博客詳情 %s" %id
    else:
        return "用戶詳情 %s" %id
#經過問號形式傳遞參數
@app.route('/d/')
def d():
    wd = request.args.get('wd') #獲取瀏覽器傳遞參數
    return '經過查詢字符串的方式傳遞的參數是,%s'%wd #請求http://127.0.0.1:8080/d/?wd=php
if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0',port=8080)

url_for

  • 將視圖函數反轉回URL,跟app.route相反
  • URL的更新大於視圖函數,因此在大規模項目中比較實用

* 基本使用

  • url_for的第一個參數是視圖函數的函數名對應的字符串(endpoint),後面的參數就是你傳遞給url;若是傳遞的參數在url中已經定義了,那麼這個參數就會被當成path的值傳遞給url;若是這個參數沒有在url中定義,那麼將變成查詢字符串的形式
from flask import Flask,url_for,request
app.route('/')
    return url_for('my_list',page=1,count=2) #這樣的話就會在頁面上構建出/post/list/1/?count=2的信息
app.route('/post/list/<page>/')
def my_list():
    return 'my list'
  • 爲何須要url_for
若是未來要修改 URL,但沒有修改 URL對應的函數名,就不用處處去替換URL了。
URL會自動處理特殊字符(轉義成十六進制),不須要手動去處理
from flask import Flask,url_for,request
@app.route('/')
def hello_world():
    return url_for('login',next='/current') #頁面返回/login/?next=%2Fcurrent登陸前的信息
    # print(url_for('my_list',page=1,count=200))
    # return 'hello world'
@app.route('/login/')
def login():
    # next = request.args.get('next') #登陸前的信息,在登錄以後仍舊保持
    return 'login'
@app.route('/list/<page>')
def my_list():
    return 'my list'
@app.route('/detail/<id>/')
def detail():
    return 'detail'
if __name__ == '__main__':
    app.run(debug=True)

自定義url轉換器

  • url的參數轉換成知足本身需求的數據類型

自定義url轉換器的方式:

  1. 實現一個類,繼承BaseConverter
  1. 在自定義的類中重寫regex,也就是這個變量的正則表達式
  2. 將自定義的類映射到app.url_map.converters上。

實現用戶訪問/posts/a+b
to_python的做用
這個方法的返回值會傳到view函數中做爲參數
to_url的做用
這個方法的返回值會調用url_for來生成符合要求的url形式

from flask import Flask,url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
#手機號碼正則
class TelephoneConveter(BaseConverter):
    regex = r'1[85734]\d{9}'
app.url_map.converters['tel'] = TelephoneConveter
#用戶訪問/posts/a+b/
class ListConverter(BaseConverter):
    def to_python(self, value):
        return value.split("+")
    def to_url(self, value):
        print(value)
        return '+'.join(value)
        # return "hello"
app.url_map.converters['list'] = ListConverter
@app.route('/')
def hello_world():
    print(url_for('posts',broads=['a','b']))
    return 'Hello World!'
@app.route('/user/<int:user_id>/')
def user(user_id):
    return "your user id is %d" %user_id
@app.route('/telephone/<tel:my_tel>/')
def my_tel(my_tel):
    return "your telephone number is %s"%my_tel
@app.route('/posts/<list:broads>/')
def posts(broads):
    # broads = broads.split("+")
    return "your posts is %s"%broads
if __name__ == '__main__':
    app.run(debug=True)

小細節

在局域網訪問站點

app.run(host='0.0.0.0')

指定端口號

默認是5000端口,修改端口以下

app.run(host='0.0.0.0',port=8899 )

ulr惟一

  • 在定義URL的時候,儘可能在url後面加/,緣由以下:

    • 若是不加/的話瀏覽器訪問這個url的時候會默認加/,這樣的話就訪問不到了
    • 搜索引擎會將不加/的url和加/的url是兩個不一樣的url,會將其誤解。

GET和POST請求

在網絡請求中有許多的請求方式,好比GET,POST,DELETE,PUT,經常使用的請求方式以下:

  • GET:也就是獲取服務器上的資源,不會修改服務器上的內容。
  • POST:就是向服務器提交文件或者數據,通常POST會對服務器的狀態產生影響。
  • 關於參數傳遞:

    • GET:把參數放到URL中,經過?xx=xxx的形式傳遞的,由於會把參數放到url中,因此視力好的話,一眼就能夠看到傳遞的參數。
    • POST:把參數放到Form Data中,避免被偷窺到的風險(也有可能經過抓包的方式被竊取),通常不安全的,不曉得提交的內容是不是帶病毒的文件。
flask中, route方法,默認只能使用 GET的方式請求url。若是想要設置本身的請求方式,那就要在 methods中多傳遞一個請求方式的參數。
實例以下:
建立url_detail的項目,項目結構以下:
├─url_detail.py
├─static
└─templates
   |_login.html
  • url_detail.py"
from flask import Flask,request,render_template
app = Flask(__name__)
@app.route('/',methods=['GET'])
def hello_world():
    return 'Hello World!'
@app.route('/list/',methods=['POST'])
def my_list():
    return 'list'
@app.route('/login/',methods=["POST","GET"])
def login():
    if request.method == 'GET':
       return render_template('login.html')
    else:
        return "Success"
if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0')
  • templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="",method="POST">
    <input type="text",name="username">
    <input type="text",name="password">
    <input type="submit",name="submmit">
</form>
</body>
</html>

URL重定向

也就是從一個頁面跳轉到另外一個頁面,也就是從新定位一個方向
分類:

  • 永久性重定向:http的狀態碼是301,多用於舊的網址廢棄了要轉到一個新的網址,確保用戶的訪問。最經典的就是jingdong.com
  • 暫時性重定向:http的狀態碼是302,表示頁面暫時性被跳轉,好比訪問一個須要權限的網址,若是當前用戶沒有登陸,應該重定向到登陸頁面。這種狀況的話就是用暫時性重定向。
在flask中,重定向是經過 flask.redirect(location,code=302)這個函數來實現的, location指的是須要重定向到的 URL,應該配合以前講過的 url_for()來是用。 code表明的是什麼類型的重定向,默認是302,能夠修改爲301實現永久重定向。
  • 小例子:
from flask import Flask,url_for,redirect,request
app = Flask(__name__)
app.debug = True
@app.route('/login/',methods=['GET','POST'])
def login():
    return 'login page'
@app.route('/profile/',methods=['GET','POST'])
def profile():
    name = request.args.get('name')
    if not name:
        return redirect(url_for('login'))
    else:
        return name
if __name__ == '__main__':
    app.run()

這樣的話就能訪問profile了:

http://127.0.0.1:5000/profile/?name=sss

關於響應

視圖函數的返回值會被自動轉換成一個響應對象,flask的轉換邏輯以下:

  • 若是返回的是一個合法的響應對象,則直接返回
  • 若是返回的是一個字符串,那麼flask會從新建立一個werkzeug.wrappers.Response對象。Response會將該字符串做爲主體,狀態碼爲200,MIME的類型爲text/html,而後返回給Response對象
  • 若是返回的是一個元組,元組中的數據類型是response,status,headers,status會覆蓋默認的200狀態碼,headers能夠是一個字典或者列表。做爲額外的消息頭
  • 若是以上的條件都不知足,flask會假設返回值是一個合法的WSGI應用程序,並經過Response.force_type(rv,request.environ)轉換成一個請求對象。
  • 自定義響應

    • 必須繼承自Response
    • 實現類方法:force_type
    • 必須指定app.response_class爲你自定義的Response
    • 若是視圖函數返回的數據既不是字符串,也不是元組,也不是Response對象,那麼會將返回值傳給force_type,而後將force_type的返回值返回給前端。
#!/usr/bin/python
# -*- coding:utf8 -*-
from flask import Flask,Response,jsonify
import json
app = Flask(__name__)
app.debug = True
#自定義響應
class JSONResponse(Response):
    @classmethod
    def force_type(cls, response, environ=None):
        '''
        這個方法只有視圖函數返回非字符串,非元組,非Response對象纔會調用
        :param response:
        :param environ:
        :return:
        '''
        print response
        print type(response)
        if isinstance(response,dict):
            #jsonify除了將字典轉換成爲json對象,還將對象封裝成了一個Response對象
            response = jsonify(response)
            #response = json.dumps(response) #這樣轉換的話程序啓動會報錯
        return super(JSONResponse,cls).force_type(response,environ) #返回父類信息
app.response_class = JSONResponse
@app.route('/')
#第一種狀況
def hello_world():
    #Response('Hello World',status=200,mimetype='text/html')
    return 'Hello World!'
#第二種狀況
@app.route('/list1/')
def list1():
    resp = Response('List1')
    resp.set_cookie('country','china')
    return resp
#第三種狀況
@app.route('/list2')
def list2():
    return 'list2',200,{'X-Name':'abc'}
@app.route('/list3/')
def list3():
    return {"username":"abc","age":11}
if __name__ == '__main__':
    app.run(host='0.0.0.0')
相關文章
相關標籤/搜索