app.route
和app.add_url_rule
app.add_url_rule
app.add_url_rule('/list/',endpoint='myweb',view_func=my_list)
這個方法是用來添加url
與視圖函數
的映射。若是沒有填寫endpoint
那麼會默認使用view_func
的名字來做爲endpoint
。
所以在使用url_for
的時候,就要看在映射的時候有沒有傳遞endpoint
參數,若是傳遞了,那麼就使用endpoint
指定的字符串。
付過沒有使用的話就使用view_func
定義的名字。css
app.route(rule,**options)
裝飾器這個裝飾器的底層就是用add_url_rule
來實現url與視圖函數映射的。html
from flask import Flask,url_for app = Flask(__name__) app.config.update({ 'DEBUG':True, 'TEMPLATES_AUTO_RELOAD':True }) @app.route('/',endpoint='index') def hello_world(): print(url_for('myweb')) return 'Hello World!' def my_list(): return 'list page!' app.add_url_rule('/list/',endpoint='myweb',view_func=my_list) #請求上下文的定義,結合url_for with app.test_request_context(): print(url_for('index')) if __name__ == '__main__': app.run()
以前咱們接觸的視圖都是函數,因此通常簡稱視圖函數。
其實視圖也能夠基於類來實現,類視圖的好處是支持繼承,可是類視圖不能跟函數視圖同樣,
寫完類視圖還須要經過app.add_url_rule(url_rule,view_func)
來進行註冊。如下將對兩種類視圖進行講解python
flask.views.View
dispatch_request
方法,之後請求過來之後,會執行這個方法。這個方法的返回值就至關因而以前的函數視圖同樣,也必須返回Request
或者子類的對象(字符串或者元組)。app.add_url_rule(rule,endpoint,view_func)
來作url映射。view_func
這個參數,要使用as_view
這個方法來轉換web
endpoint
,那麼在使用url_for
反轉的時候,就要使用endpoint
指定的那個值,若是沒有指定那個值,就使用as_view
中指定的視圖名字來做爲反轉。from flask import Flask,views,url_for app = Flask(__name__) class ListView(views.View): def dispatch_request(self): return 'list view' #app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list')) app.add_url_rule('/list/',view_func=ListView.as_view('list')) with app.test_request_context(): print(url_for('list')) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run(debug=True)
from flask import Flask,url_for,views,jsonify,render_template app = Flask(__name__) app.config.update({ 'DEBUG':True, 'TEMPLATES_AUTO_RELOAD':True }) #自定義封裝,返回json數據 class JSONView(views.View): def get_data(self): raise NotImplementedError def dispatch_request(self): return jsonify(self.get_data()) class ListView(JSONView): def get_data(self): return { 'username':'wanghui', 'password':123456, } app.add_url_rule('/list/',endpoint='my_list',view_func=ListView.as_view('list')) #有幾個視圖,須要返回相同的變量(廣告頁面) class ADSView(views.View): def __init__(self): super(ADSView, self).__init__() self.context = { 'ads':"今年過節不收禮,收禮只收腦白金" } class RegistView(ADSView): def dispatch_request(self): self.context.update({'username':'abcd'}) return render_template('register.html',**self.context) class LoginView(ADSView): def dispatch_request(self): return render_template('login.html',**self.context) # class LoginView(views.View): # def dispatch_request(self): # return render_template('login.html',ads="今年過節不收禮,收禮只收腦白金") # class RegistView(views.View): # def dispatch_request(self): # return render_template('register.html',ads="今年過節不收禮,收禮只收腦白金") app.add_url_rule('/login/',view_func=LoginView.as_view('login')) app.add_url_rule('/regist/',view_func=RegistView.as_view('regist')) @app.route('/') def hello(): return "heello" if __name__ == '__main__': app.run()
request.method == 'POST'
來搞了。from flask import Flask,views,render_template,request app = Flask(__name__) class LoginView(views.MethodView): def __render(self,error=None): return render_template('login.html',error=error) def get(self,error=None): # return render_template('login.html',error=error) return self.__render() def post(self): username = request.form.get('username') password = request.form.get('password') if username == 'wanghui' and password == '111111': return 'login success' else: # return render_template('login.html',error="username or password error,retry!") # return self.get(error="username or password error,retry!") return self.__render(error="username or password error,retry!") app.add_url_rule('/login/',view_func=LoginView.as_view('login')) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run(debug=True,port=9090)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="" method="post"> <table> <tr> <td>用戶名</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密碼</td> <td><input type="password" name="password"></td> </tr> <tr> <td></td> <td><input type="submit" value="當即登錄"></td> </tr> </table> {% if error %} <p style="color: red;">{{ error }}</p> {% endif %} </form> </body> </html>
兩種類型的裝飾器json
- 若是使用的是函數視圖, 那麼定義的裝飾器必須放在
app.route
下面,不然起不到任何做用
decorators
類屬性,裏面裝的就是全部的裝飾器from flask import Flask,request,views from functools import wraps app = Flask(__name__) #定義裝飾器 def login_required(func): @wraps(func) def wrapper(*args,**kwargs): username = request.args.get('username') if username and username == 'wanghui': return func(*args,**kwargs) else: return "請先登陸" return wrapper @app.route('/settings/') @login_required def settings(): return '這是設置頁面' #這樣請求就行http://127.0.0.1:9091/settings/?username=wanghui #類視圖添加裝飾器 class ProfileView(views.View): decorators = [login_required] def dispatch_request(self): return "這是我的中心" app.add_url_rule('/profile/',view_func=ProfileView.as_view('profile'))
將大型項目分層解耦,實現模塊化,結構更加清晰。能夠將相同的模塊放在同一個藍圖下,同一個文件夾中。方便管理。
from flask import Blueprint user_bp = Blueprint('user',__name__) #至關因而定義`app = Flask(__name__)`
from blueprints.user import user_bp app.regist_blueprint(user_bp) #實現註冊藍圖
URL
的時候有個前綴,那麼能夠在定義藍圖的時候加上url_prefix
from flask import Blueprint user_bp = Blueprint('user',__name__,url_prefix='/user') # 特別注意斜槓
藍圖模板文件查找:flask
templates
文件夾中存在對應的模板文件,就能夠直接使用templates
文件夾中存在相應的模板文件,那麼就在定義藍圖的指定路徑中查找,能夠設置相對路徑,就要在藍圖文件相同路徑下的文件夾。
from flask import Blueprint,render_template news_bp = Blueprint('news',__name__,url_prefix='/news',template_folder='news') @news_bp.route('/list/') def news_list(): return render_template('news_list.html')
藍圖中的靜態文件查找:app
url_for('static')
,那麼只會在app指定的靜態文件夾目錄下查找靜態文件url_for('news.static')
,那麼會到藍圖指定的static_folder
下查找靜態文件。url_for
到藍圖中的視圖函數的時候,要反轉藍圖中的視圖函數爲url,那麼就用該在使用url_for
的時候使用url_for('news.news_list')
否則就找不到這個endpoint。subdomain
來指定這個子域名from flask import Blueprint cms_bp = Blueprint('cms',__name__,subdomain='cms')
app.config['SERVER_NAME']='baidu.com'
來指定跟域名app.config['SERVER_NAME'] = 'crop.com:9099'
127.0.0.1 crop.com 127.0.0.1 cms.crop.com
5.訪問dom
cms.crop.com:9099
blue_print_e ├── blue_print_e.py ├── blueprints │ ├── bok.py │ ├── cms.py │ ├── movie.py │ ├── news_css │ │ └── news_list.css │ ├── news.py │ ├── news_tmp │ │ └── news_list.html │ └── user.py ├── static │ └── news_list.css └── templates ├── index.html └── news_list.html
blue_print_e.py
from flask import Flask,url_for,render_template from blueprints.user import user_bp from blueprints.news import news_bp from blueprints.cms import cms_bp app = Flask(__name__) app.config['SERVER_NAME'] = 'crop.com:9099' app.register_blueprint(user_bp) app.register_blueprint(news_bp) app.register_blueprint(cms_bp) # ip地址不能有子域名 @app.route('/') def hello_world(): print(url_for('news_tmp.news_list')) #使用藍圖名字.視圖函數的名字 return render_template('index.html') if __name__ == '__main__': app.run(debug=True,port=9099)
blueprints/news.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Blueprint,render_template,url_for news_bp = Blueprint('news_tmp',__name__,url_prefix='/news_tmp',template_folder='news_tmp',static_folder='news_css') @news_bp.route('/list/') def news_list(): print(url_for('news.news_detail')) return render_template('news_list.html') @news_bp.route('/detail') def news_detail(): return "詳情頁面"
blueprints/user.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Blueprint user_bp = Blueprint('user',__name__,url_prefix='/user') @user_bp.route('/profile/') def profile(): return "我的中心" @user_bp.route('/settings/') def settings(): return "設置頁面"
blueprint/cms.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Blueprint cms_bp = Blueprint('cms',__name__,subdomain='cms') @cms_bp.route('/') def index(): return 'cms index'
blueprints/news_css/
body { color: fuchsia; font-size: 90px; background: red; }