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()**strong text**

debug模式

  • 爲什麼要開啓DEBUG模式?
    • 如果開啓了debug模式,name代碼在調試過程中出現了異常,在瀏覽器頁面中可以看到具體的報錯信息,以及具體的錯誤代碼位置,方便開發者調試。
    • 如果flask開啓了debug模式,name以後再python中修改任何代碼,只要在pycharm中使用ctrl+s即可保存重載,不需要手動去重載程序
  • 如何配置debug模式:
    1. app.run()
      app.run(debug=True)
    2. app.debug
      app.debug = True
    3. 配置信息方式(使用參數形式的方式)
      app.config.update[DEBUG=True]
      #其實也就是update了config字典
    4. 通過配置文件的形式
  • 創建一個config.py的配置文件,寫入
    DEBUG = True
  • 然後在你的app.py文件中寫入
    app.config.from_object(config) #即可讀取配置文件中的DEBUG=True
    
    **debug PIN碼**
    ``` python
    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)
    
    然後在頁面上調試代碼的時候用到。
    也是爲了安全考慮。
    ## 配置文件兩種方式詳解
  • 第一種方式:
    在項目主路徑下創建config.py
    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裏面的配置:

    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/&lt;page&gt;')
    def my_list():
    return 'my list'
    @app.route('/detail/&lt;id&gt;/')
    def detail():
    return 'detail'
    if __name__ == '__main__':
    app.run(debug=True)

    自定義url轉換器

  • url的參數轉換成滿足自己需求的數據類型
    自定義url轉換器的方式:
    1. 實現一個類,繼承BaseConverter
    2. 在自定義的類中重寫regex,也就是這個變量的正則表達式
    3. 將自定義的類映射到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/&lt;int:user_id&gt;/')
      def user(user_id):
      return "your user id is %d" %user_id
      @app.route('/telephone/&lt;tel:my_tel&gt;/')
      def my_tel(my_tel):
      return "your telephone number is %s"%my_tel
      @app.route('/posts/&lt;list:broads&gt;/')
      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')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章