整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          python超級明星web開發框架之Flask教程

          lask簡介

          Flask是一個相對于Django而言輕量級的Web框架。

          和Django大包大攬不同,Flask建立于一系列的開源軟件包之上,這其中 最主要的是WSGI應用開發庫Werkzeug和模板引擎Jinja:

          策略 :werkzeug和Jinja這兩個庫和Flask一樣,都是pocoo團隊開發的。這 或許體現了pocoo與Django競爭時關于生態的一種策略,這種策略的自然延伸是Flask框架中沒有包含數據庫方面的構件,無論ORM還是其他。

          關注點 :Flask是一個WSGI應用框架,這意味著我們進行Flask開發時,不需要 關注網絡方面的操作,Flask應用的入口是封裝過的網絡請求包,出口是 網絡響應,我們僅需要關注這個階段內的處理邏輯。

          WSGI服務器 :Flask雖然內置了簡單的WSGI服務器,但其性能僅僅適用于開發期的調試。 Flask官網推薦了多種WSGI服務器,實現方式從多進程到多線程到協程, 這方面的選擇我們在本課程中將不涉及。

          REST適應性 :雖然Flask和Django一樣,最初的出發點都是服務端的動態網頁應用。但 Flask的設計使之也相當適用于面向資源的REST架構,在越來越移動化 并且單頁應用越來越重要的WEB開發領域,這是Flask相對于Django相當 大的優勢。

          這里推薦大家一個學習flask的教程,本文的內容也是轉自該教程。


          Hello Flask

          編寫一個基于Flask的hello world相當容易:

          1、導入Flask類

          from flask import Flask
          

          Flask類是Flask框架的核心類,它實現了WSGI應用規范。

          2、創建Flask實例

          app = Flask(__name__)
          

          Flask構造函數的第一個參數指定一個引入名/importname。Flask框架 使用這個名字進行靜態資源、模板、錯誤信息的定位。除非你清楚的理解它的 作用,通常情況下,我們總應該使用特殊變量_name。

          Flask實例是可調用的(具有call方法),這個實例可以直接對接 WSGI服務器。

          3、注冊路由

          @route('/')
          def index():
              return 'Hello,Flask!'
          

          注冊路由就是建立URL規則和處理函數之間的關聯。Flask框架依賴于路由 完成HTTP請求的分發。

          路由中的函數被稱為視圖函數,其返回值將作為HTTP響應的正文內容。

          4、對接并啟動WSGI服務器

          Flask封裝了一個簡單的開發用WSGI服務器,我們可以通過調用run() 啟動服務器運行:

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

          概述

          路由是MVC架構的Web框架中相當重要的一個概念,也是本節課程的重點。

          顧名思意,路由就是在迷茫中找出一條路的意思。在Flask框架中的路由就表示為用戶請求的URL找出其對應的處理函數之意。


          在本節課程,我們將主要從以下幾個方面講解Flask框架中的路由:

          如何為應用注冊路由? 如何為路由指定其支持的HTTP方法? 如何匹配動態URL? 如何對URL中的變量類型進行過濾? 如何理解訪問點/endpoint? 如何為應用設定靜態路由? 如何避免硬編碼指向其他視圖的URL?

          注冊路由

          在Flask應用中,路由是指用戶請求的URL與視圖函數之間的映射。Flask框架 根據HTTP請求的URL在路由表中匹配預定義的URL規則,找到對應的視圖函數, 并將視圖函數的執行結果返回WSGI服務器:


          可見路由表在Flask應用中處于相當核心的位置。路由表的內容是由應用開發者填充。

          route裝飾器 :可以使用Flask應用實例的route裝飾器將一個URL規則綁定到 一個視圖函數上。

          例如,下面的示例將URL規則/test綁定到視圖函數test()上:

          @app.route('/test')
          def test():
              return 'this is response'
          

          如果這個應用部署在主機ezhost.com的根目錄下,那么當用戶訪問:

          http://ezhost.com/teset
          

          Flask框架就會調用我們的test()函數,其返回結果就傳遞給WSGI服務器發送給訪問者。

          add_url_rule() :另一種等價的寫法是使用Flask應用實例的add_url_route()方法。 下面的示例注冊了一個與前例相同的路由:

          def test():
              return 'this is response'
          app.add_url_route('/test',view_func=test)
          

          其實,route裝飾器內部也是通過調用add_url_route()方法實現的路由注冊。 但是顯然,使用裝飾器使代碼看起來更優雅一些。

          為路由指定HTTP方法

          默認情況下,Flask路由僅支持HTTP的GET請求。可以使用methods關鍵字參數,在注冊 路由時顯式地聲明視圖方法支持的HTTP方法。

          例如,下面的示例將URL規則/auth綁定到視圖函數v_auth(),這個路由僅支持POST方法:

          @app.route('/auth',methods=['POST'])
          def v_auth():pass
          

          指定多種HTTP方法支持

          關鍵字參數methods的類型為list,因此可以同時指定多種HTTP方法。

          下面的示例中,使URL規則/user同時支持POST方法和GET方法:

          @app.route('/user',methods=['POST','GET'])
          def v_users():
              if request.method == 'GET':
                  return ... # 返回用戶列表
              if request.method == 'POST'
                  return ... #創建新用戶
          

          這個特性使Flask非常易于開發REST架構的后臺服務,而不僅僅局限于傳統的動態網頁。

          匹配動態URL

          有時我們需要將同一類URL映射到同一個視圖函數處理,比如,使用同一個視圖函數 來顯示不同用戶的個人檔案。我們希望以下的URL都可以分發到同一個視圖函數:


          在Flask中,可以將URL中的可變部分使用一對小括號<>聲明為變量, 并為視圖函數聲明同名的參數:

          @app.route('/user/<uname>')
          def v_user(uname):
              return '%s\'s Profile' % uname
          </uname>
          

          在上面的示例中,URL規則中的<uname>表示這部分是可變的,Flask將提取用戶請求的 URL中這部分的內容,并作為視圖函數v_user()的uname參數進行調用。

          URL變量類型過濾

          考慮下面的示例,我們希望通過HTTP共享文件夾/var/readonly中的文件:

          /var
              /readonly
                  /a.txt
                  /b.txt
                  /repo
                     /c.txt
                     /d.txt
          

          簡單思考一下就有答案了。我們可以構造URL規則/file/<fname>,然后直接 讀取文件內容返回給用戶。注冊如下的路由:

          @app.route('/file/<fname>')
          def v_file(fname):
              fullname = os.path.join('/var/readonly',fname)
              f = open(fullname)
              cnt =  f.read()
              f.close()
              return cnt
          </fname>
          

          測試結果表明,/file/a.txt和/file/b.txt都沒有問題,但是/file/repo/c.txt和 /file/repo/d.txt卻會失敗。

          這是因為,默認情況下,在URL規則中的變量被視為不包含/的字符串。/file/repo/c.txt 是沒有辦法匹配URL規則/file/<fname>的。

          可以使用內置的path轉換器告訴Flask框架改變這一默認行為。path轉換器允許 規則匹配包含/的字符串:

          @app.route('/file/<path:fname>')
          </path:fname>
          

          在Flask中,轉換器/converter用來對從URL中提取的變量進行預處理,這個過程 發生在調用視圖函數之前。Flask預置了四種轉換器:

          1. string - 匹配不包含/的字符串,這是默認的轉換器
          2. path - 匹配包含/的字符串
          3. int - 只有當URL中的變量是整型值時才匹配,并將變量轉換為整型
          4. float - 只有當URL中的變量是浮點值時才匹配,并將變量轉換為浮點型

          訪問點/endpoint

          我們一直強調,路由的作用是根據請求的URL,找到對應的視圖函數。這沒錯,但是在 Flask框架中,請求任務的分發并不是直接從用戶請求的URL一步定位到視圖函數, 兩者之間隔著一個訪問點/endpoint。

          以下面的代碼為例,我們看Flask怎樣實現請求的分發:

          @app.route('/home')
          def home():pass
          

          在Flask內部使用兩張表維護路由:

          • url_map :維護URL規則和endpoint的映射
          • view_functions :維護endpoint和視圖函數的映射。

          以用戶訪問URL/home為例,Flask將首先利用url_map找到所請求URL對應的 endpoint,即訪問點home,然后再利用view_functions表查找home這個訪問點 對應的視圖函數,最終匹配到函數home():


          默認訪問點 :當我們使用route裝飾器注冊路由時,默認使用被裝飾函數的 函數名(name)作為訪問點,因此,你看到上面的表中,路由中的訪問點為home。

          自定義訪問點 :可以在使用route裝飾器或調用add_url_rule()方法注冊路由時,使用 endpoint關鍵字參數改變這一默認行為:

          @app.route('/home',endpoint='whocare')
          def home():pass
          

          此時的兩張路由表將變成這樣:


          靜態目錄路由

          當創建應用實例時,Flask將自動添加一條靜態目錄路由,其訪問點 始終被設置為static,URL規則默認被設置為/static,本地路徑默認被 設置為應用文件夾下的static子文件夾:

          +------------------------------------------------------------+ | url rule | endpoint | view_function | | /static | static | Flask.send_static_file | +------------------------------------------------------------+ 如果你的應用目錄如下:

          /app
              /web.py
              /static
                  /main.css
                  /jquery.min.js   
          

          那么啟動應用后就可以通過URL/static/main.css訪問static文件夾下的main.css了。

          除了訪問點被固定為static,靜態目錄的URL規則和本地目錄都是可以根據應用情況進行調整。

          改變默認的本地路徑 :可以在創建應用對象時使用關鍵字參數static_folder改變 默認的靜態文件夾。例如,你的靜態文件都存放在應用下的assets目錄下, 那么可以按如下的方式創建應用對象:

          app = Flask(name,static_folder='assets') 也可以使用一個絕對路徑:

          app = Flask(name,static_folder='/var/www/static') 改變默認的本地路徑并不會對路由表產生影響。

          改變默認的URL規則 : 如果不喜歡靜態目錄URL/static,也可以在創建應用 對象時使用關鍵字參數static_url_path換一個別的名字。

          下面的示例中,將應用下的assets文件夾注冊為靜態目錄/assets:

          app = Flask(name,static_folder='assets',static_url_path='/assets') 當應用運行后,通過URL/assets/main.css就可以訪問assets文件夾下的 main.css文件了。

          這時的路由表變化為:

          +------------------------------------------------------------+ | url | endpoint | view_function | | /assets | static | Flask.send_static_file | +------------------------------------------------------------+

          構造URL

          在一個實用的視圖中,不可避免地存在指向其他視圖的鏈接。在之前的課程示例中,我們 都是在視圖函數中這樣硬編碼這些鏈接URL的:

          @app.route('/')
          def v_index():
              return '<a href="/tech">tech</a>'
          @app.route('/tech') 
          def v_tech():pass
          

          大部分情況下這種硬編碼URL是可以工作的。但如果這個應用被掛在WSGI服務器的一個 子路徑下,比如:/app1,那么用戶訪問URL/tech是不會成功的,這時應當訪問/app1/tech 才可以正確地路由到視圖函數v_tech()。

          我們應當使用訪問點讓Flask框架幫我們計算鏈接URL。簡單地給url_for()函數傳入 一個訪問點,它返回將是一個可靠的URL地址:

          @app.route('/')
          def v_index():
              print url_for('v_contacts')  # /contact
              return 'see console output!'
          @app.route('/contact')
          def v_contacts():pass
          

          添加查詢參數 : 使用關鍵字參數,可以在構造的URL中生成查詢串。下面的調用將生成 /contact?format=json

          @app.route('/')
          def v_index():
              print url_for('v_contacts',format='json')
              return  ''
          @app.route('/contact') 
          def v_contacts():pass
          

          添加URL變量 : 如果指定訪問點對應的視圖函數接收參數,那么關鍵字參數將生成對應的參數URL。下面的 示例將生成/contact/Julia?format=html:

          @app.route('/')
          def v_index():
              print url_for('v_contact',name='Julia',format='html')
              return ''
          @app.route('/contact/<name>')
          def v_contact(name):pass
          </name>
          

          添加錨點 :使用_anchor關鍵字可以為生成的URL添加錨點。下面的示例將生成URL /contact#part2

          @app.route('/')
          def v_index():
              print url_for('v_contacts',_anchor='part2')
          @app.route('/contact')
          def v_contacts():pass
          

          外部URL : 默認情況下,url_for()生成站內URL,可以設置關鍵字參數_external 為True,生成包含站點地址的外部URL。下面的示例將生成URLhttp://<x.y.z>/contacts:

          源:Python爬蟲與數據挖掘

          作者:Python進階者

          前言

          今天來給大家說一個Python的輕量級web開發框架-------Flask,為什么要推薦它呢?當然是因為它夠輕量級了,開發迅速是它的特點,當然它也有缺點,不過這里不說,因為既用它又說它差感覺不好。

          一、安裝flask

          pip install flask #需要注意的是,還有flake,那個是檢查錯誤的模塊,不要搞混了

          可以看到成功了,總共下載了四個模塊,分別是對應的web開發中的模板渲染,網絡服務都是一些flask依賴包。

          二、flask的用法

          1.啟動

          既然說到用法,那第一個就肯定得說說它是怎么啟動的,不然別人哪里還學的下去啊,廢話少說,開干。

          from flask import Flask
          app=Flask(__name__) #創建應用實例
          
          
          @app.route('/')  # route裝飾器創建路由
          def hello():  # 訪問此路由時執行的視圖函數
              return 'hello' # 視圖函數的返回值,又叫‘響應’
          if __name__ == '__main__':
              app.run(debug=True) #開始運行flask應用程序,以調試模式運行
              
          #可以設置啟動的host地址和端口號,具體方法:
          app.run(host='192.168.1.2',port=3243)

          從上面可以看出,因為我修改了視圖函數和返回值,只需在瀏覽器刷新即可,完全不用退出重啟,sublime text 3真是神器啊,給力,墻裂建議大家使用。

          2.創建Flask應用注意事項

          要想創建一個Flask應用,首先我們要建立一個項目文件夾,里面至少要有兩個文件夾,一個存放媒體文件(static),一個存放網頁文件(templates),如果Python程序不多,可以不用給它單獨建立文件夾。Flask不像Django一樣可以自動創建文件夾,需要我們自己創建。如果你想查看flask創建的路由信息:

          url_map存儲的是url與endpoint的映射。那么這個endpoint是什么意思了?實際上,當請求傳來一個url的時候,會先通過rule找到endpoint,然后再根據endpoint再找到對應的視圖函數。通常,endpoint的名字都和視圖函數名一樣。這里還有一點特別注意,那就是所有的控制臺輸出信息語句必須寫在app.run()之前,否則不起作用。

          3.Flask的妙用

          我們可以看到Flask里面有一個name,這個是為了啟動模板專門設立的,除了這個,它還有:

          static_url_path:靜態網頁地址

          static_folder:靜態地址,默認為static文件夾

          template_folder:模板文件夾,默認為templates文件夾

          4.添加配置文件

          1)直接在app.run()函數里添加

          比如以調試模式運行Flask應用就可以使用:app.run(debug=True)

          2)直接配置

          app.config=True

          3)建立配置文件

          在項目文件夾根目錄建立一個配置文件夾,名字為 hw.hw,后綴名你隨便取,內容為 DEBUG=True,然后在app.run()前面添加app.config.from_pyfile('hw.hw') 即可。

          5.視圖函數用法

          1)下級頁面

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

          2)轉換器

          @app.route('/index/<int:num>') #定義轉換器名字num
          def num(num): #將轉換器傳入函數中
              if num>10: #如果它的值大于10輸出dog,小于10輸出pig
                  return 'dog'
              else:
                  return 'pig'

          這里需要說到的是,轉換器主要是將頁面后的值作為某一個標準來得到另一個頁面,我們常看到的加密字符串就是用這個做的,那么它有哪些類型呢?

          Flask的默認轉換器:DEFAULT_CONVERTERS = {
          ‘default’: UnicodeConverter,
          ‘string’: UnicodeConverter,
          ‘any’: AnyConverter,
          ‘path’: PathConverter,
          ‘int’: IntegerConverter,
          ‘float’: FloatConverter,
          ‘uuid’: UUIDConverter,}

          除此之外,我們也可以自定一轉換器,定義轉換器需要使用依賴包,方法如下:

          class rc(BaseConverter):      
           # 重寫父類的屬性,定義轉換?規則
              def __init__(self,url_map):
                  super(rc,self).__init__(url_map)
                  #驗證QQ郵箱的正則表達式
                  self.regex ='[0-9a-zA-Z_]{0,19}@qq.com'
              #定義視圖函數下的返回值
              def to_python(self,value):
                  val=value
                  return val
              def to_url(self,value):#返回url
                  return value
          app.url_map.converters['em'] = rc #將自定義的轉換器添加到轉換器列表中
          @app.route('/emm/<em:email>') #加入新的轉換器
          def email(email):
              return 'email is:%s' % email #返回email

          可以通過反向解析將添加了自定義轉換器的視圖函數拿來用,這里需要用到重定向和反向解析:

          @app.route('/search')
          def jj():
              url=url_for('email',email='2091500484@qq.com')
              return redirect(url)

          如果不注明轉換器類型,就是默認的字符串型:

          @app.route('/hw/<boy>') 
          def hw(boy):
              return 'boy:%s'%boy

          還可以定義默認的轉換器的默認值:

          
          @app.route('/ha/<string:haid>',defaults={'haid':'hello,boy'}) #設置默認值
          def ha(haid):
              return 'haid:%s'%haid

          3)多個路由指向同一地址

          
          @app.route('/1')
          @app.route('/2')
          def fg():
              return '1122'

          這里訪問下級頁面1或者頁面2都會得出同樣的結果’1122‘

          6.重定向

          重定向即是指從一個網頁跳轉到另一個網頁,相當于刷新之后的操作,這里涉及到flask里的兩個模塊(redirect,url_for)。

          1)直接跳轉

          直接跳轉到路由下

          
          from flask import redirect,url_for
          @app.route('/refer')
          def refer():
              return redirect('/1')

          這樣就可以直接跳轉到路由函數fg中并顯示返回值。

          2)間接跳轉

          我們可以先訪問路由函數,然后跳轉到相應內容頁面

          
          @app.route('/ref')
          def ref():
              return redirect(url_for('fg')) #跳轉

          這樣直接訪問ref子頁面就可以直接跳轉到相應頁面了

          7.定義錯誤頁面

          有兩種方式,一是使用系統的abort直接賦值,二是使用自定義errorhandler函數。

          1)abort

          直接使用系統自帶的錯誤內容

          
          @app.route('/use/<id>')
          def get_use(id):
              if int(id)<10:
                  abort(404)
              elif int(id)>20:
                  return '---Error---'
              return 'hello:%s'%str(id)

          2)errorhandler

          自定義錯誤頁面內容

          
          @app.errorhandler(404)
          def error(err):
              return 'hello,%s'%err

          3)定義錯誤頁面

          它可以將自定義的錯誤寫入到頁面中,平時會用的比較多。

          
          @app.route('/error1')
          def err1():
              error1=('index error',666,[('key','div'),('value','zero')])
              return error1

          當然還有一種表述方式:

          
          @app.route('/error2')
          def err2():
              error2=('login error',444,{'serise':'100','dataframe':'200'})
              return error2  

          4)設置請求

          這里需要說到一個新的模塊make_response(),當然你也可以使用Response()。

          
          @app.route('/error3')
          def err3():
              resp=make_response('search error') #這里只需把make_response()換成Response()即可
              resp.status='400'
              resp.headers['hrr']='zjj'
              resp.headers['hw']='zj'
              return resp

          8.json數據讀取

          flask中有個非常給力的可以處理json數據的模塊,jsonify。

          
          @app.route('/json1')
          def json1():
              data={'name':'HW','first':'ZJ'}
              return jsonify(data)
          
          
          @app.route('/json2')
          def json2():
              return jsonify(hour=12,second=21)

          9.cookie的操作

          1)設置cookie

          #cookie的設置
          #set_cookie(key, value='', max_age=None, expires=None,path='/', domain=None, secure=False, httponly=False,samesite=None)
          
          
          #key:鍵
          #value:值
          #max_age:設置過期時間(秒)
          #expires:設置過期時間,時間戳的形式(1970離現在的時間)
          #path:當前主域名
          #domain:子域名
          #設置cookie和headers
          @app.route('/set_cookie')
          def set_cookie():
              response=make_response('cookie設置成功')
              #cookie有效時長30天也可以是hour second minute
              time=datetime.datetime.today()+datetime.timedelta(days=30)#設置cookie的有效時長
              response.set_cookie('user','admin',expires=time) #設置用戶名的cookie
              response.set_cookie('pass','123456',expires=time) #設置密碼的cookie
              response.headers['X-Something']='mything' #這里不允許出現中文
              response.headers['Server']='Linux' #服務器名稱
              return response

          2)獲取cookie

          這里需要用到一個模塊request,它相當于模擬一個請求,你可以把它當做requests模塊一樣。

          @app.route('/get_cookie')
          def get_cookie():
              name="用戶名:"+request.cookies.get('user')+"密碼:"+request.cookies.get('pass')
              return name

          3)刪除cookie

          有兩種刪除方式來刪除cookie。

          1.通過設置cookie過期時間為0即可刪除

          @app.route('/del_cookie1')
          def del_cookie1():
              response=make_response('delete cookie 1')
              response.set_cookie('user','',expires=0)
              response.set_cookie('pass','',expires=0)
              return response

          2.直接刪除cookie

          @app.route('/del_cookie2')
          def del_cookie2():
              response=make_response('delete cookie 2')
              response.delete_cookie('user')
              response.delete_cookie('pass')
              return response

          10.session操作

          session里面保留的就是會話內容,它存在于cookie當中,通過它我們可以直接登陸某些已經登陸過的系統。要想操作session我們需要引入為它專門準備的session模塊,還有需要配置安全秘鑰才可以使用session。

          1)設置session

          一、配置安全秘鑰:

          
          app.config['SECRET_KEY']=os.urandom(30)

          二、設置session字典

          
          session['user']='hw'
          session['pass']='zj'

          三、設置session過期方式

          
          session.parmanent=True #默認31天后過期
          #session兩個小時過期
          app.config['PERMANENT_SESSION_LIFETIME']= timedelta(hour=2)

          四、綜合代碼

          @app.route('/session1')
          def session1():
              session['user']='hw'
              session['pass']='zj'
              session.parmanent=True #默認31天后過期
              return 'login success'

          可以看到session成功設置在cookie里面了,并且瀏覽器也記錄了。當然你也可以只設置cookie,不過為了安全建議你設置session。

          2)獲取session

          跟cookie獲取有點不同。

          一、get()獲取

          
          @app.route('/session2')
          def session2():
              us=session.get("user")
              pa=session.get("pass")
              return 'hello %s %s'%(us,pa)

          二、索引獲取

          這種方式如果獲取不到值容易產生異常,建議用上一種方法,除非你知道一定能獲取到值。

          
          @app.route('/session2')
          def session2():
              us=session["user"]
              pa=session["pass"]
              return 'hello %s %s'%(us,pa)

          3)刪除session

          也有兩種方法,不過一種是一個一個刪除,另一種則是全部刪除。

          一、逐一刪除

          @app.route('/session3')
          def session3():
              session.pop('user',None)
              session.pop('pass',None)
              return 'delete successful!!!!'

          二、全部刪除

          @app.route('/session4')
          def session4():
              session.clear()
              return 'delete successful!!!!'

          11.總結

          本文著重講解了Flask的最基礎的用法,Flask是一個十分優秀的web開發框架,它可以十分迅速的開發出web應用,但是它需要依賴眾多的包才能完善更多的功能。這里只是講述了Flask一半的知識,下一篇文章,繼續給大家盤點,一起學習,共同進步!

          eb應用程序通常需要一個靜態文件,例如支持顯示網頁的JavaScript文件或CSS文件。 通常,可以通過配置Web服務器提供這些服務,但在開發過程中,這些文件將從包中的靜態文件夾或模塊旁邊提供,它將在應用程序的/static上提供。

          使用特殊的端點“靜態”來為靜態文件生成URL。

          在以下示例中,index.html中的HTML按鈕的OnClick事件調用hello.js中定義的javascript函數,該函數在Flask應用程序的URL => / 中呈現。

          示例

          # Filename : example.py
          # Copyright : 2020 By Nhooo
          # Author by : www.cainiaojc.com
          # Date : 2020-08-08
          from flask import Flask, render_template
           app = Flask(__name__)
           @app.route("/")
           def index():
               return render_template("index.html")
           if __name__ == '__main__':
               app.run(debug = True)

          index.html 中的HTML腳本如下所示。

          # Filename : example.py
          # Copyright : 2020 By Nhooo
          # Author by : www.cainiaojc.com
          # Date : 2020-08-08
          <html>
              <head>
                 <script type = "text/javascript" 
                    src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
              </head>
              <body>
                 <input type = "button" onclick = "sayHello()" value = "Say Hello" />
              </body>
           </html>

          文件: hello.js 中定義包含 sayHello() 函數。


          主站蜘蛛池模板: 亚洲日韩中文字幕一区| 亚洲另类无码一区二区三区 | 在线视频一区二区三区四区| av无码精品一区二区三区四区| 久久亚洲AV午夜福利精品一区| 日韩精品一区二区三区毛片| 天堂Aⅴ无码一区二区三区| 亚洲一区二区三区免费视频| 亚洲第一区在线观看| 无码日韩人妻av一区免费| 本免费AV无码专区一区| 全国精品一区二区在线观看| 海角国精产品一区一区三区糖心 | 国产精品一区二区AV麻豆 | 亚洲av乱码中文一区二区三区| 国模无码人体一区二区| 国模吧无码一区二区三区| 八戒久久精品一区二区三区| 久热国产精品视频一区二区三区| 无码一区二区三区视频| 日韩电影一区二区三区| 国产无码一区二区在线| 全国精品一区二区在线观看| 精品3d动漫视频一区在线观看| 日本精品视频一区二区三区| 中文字幕无码不卡一区二区三区| 蜜臀AV在线播放一区二区三区| 亚洲爆乳无码一区二区三区| 日本在线一区二区| 亚洲熟妇av一区| 国模视频一区二区| 一区二区精品视频| 寂寞一区在线观看| 亚洲色精品三区二区一区| 精品国产免费一区二区| 一区二区三区影院| 亚洲第一区二区快射影院| 国产品无码一区二区三区在线| 国产免费av一区二区三区| 精品久久一区二区三区| 亚洲无码一区二区三区|