Bootstrap 是 Twitter 開發的一個開源框架,它提供的用戶界面組件可用於建立整潔且具備吸引力的網頁,並且這些網頁還能兼容全部現代 Web 瀏覽器. Bootstrap 是客戶端框架,所以不會直接涉及服務器。服務器須要作的只是提供引用了 Bootstrap 層疊樣式表(CSS)和 JavaScript 文件的 HTML 響應, 而且 HTML、CSS 和 JavaScript 代碼中實例化所需組件。這些操做最理想的執行場所就是模版。 Flask-Bootstrap 能夠在程序中集成 Bootstrap
安裝:css
pip install flask-bootstrap
使用:html
from flask_bootstrap import Bootstrap ...... bootstrap = Bootstrap(app)
初始化 Flask-Bootstrap 以後,就能夠在程序中使用一個包含全部Bootstrap 文件的基模版。這個模版利用 Jinja2 的模版繼承機制,讓程序擴展一個具備基本頁面結構的基模版,其中就有用來引入 Bootstrap 的元素。python
bootstrap的base.html文檔:mysql
{% block doc -%} <!DOCTYPE html> <html{% block html_attribs %}{% endblock html_attribs %}> {%- block html %} <head> {%- block head %} <title>{% block title %}{{title|default}}{% endblock title %}</title> {%- block metas %} <meta name="viewport" content="width=device-width, initial-scale=1.0"> {%- endblock metas %} {%- block styles %} <!-- Bootstrap --> <link href="{{bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap')}}" rel="stylesheet"> {%- endblock styles %} {%- endblock head %} </head> <body{% block body_attribs %}{% endblock body_attribs %}> {% block body -%} {% block navbar %} {%- endblock navbar %} {% block content -%} {%- endblock content %} {% block scripts %} <script src="{{bootstrap_find_resource('jquery.js', cdn='jquery')}}"></script> <script src="{{bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap')}}"></script> {%- endblock scripts %} {%- endblock body %} </body> {%- endblock html %} </html> {% endblock doc -%}
繼承Bootstrap 文件的基模版,編寫適用於本身項目的基模板。jquery
{#本身編寫一個基類模板#} {% extends 'bootstrap/base.html' %} {% block styles %} {{ super() }} <link rel="stylesheet" href="../static/css/main.css"> {% endblock %} {% block navbar %} <nav class="navbar navbar-default"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="index.html"></a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="#">首頁<span class="sr-only">(current)</span></a></li> <li><a href="#">新聞</a></li> <li><a href="#">國際</a></li> <li><a href="#">國內</a></li> <li><a href="/sysinfo/">系統信息</a></li> <li><a href="#">登錄用戶</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if 'user' in session %} <li><a href="login.html"><span class="glyphicon glyphicon-user"></span> {{ session.user }}</a></li> <li><a href="/logout/"><span class="glyphicon glyphicon-log-in"></span> 註銷 </a></li> {% else %} <li><a href="/login/"><span class="glyphicon glyphicon-log-in"></span> 登錄</a></li> {% endif %} <li><a href="/register/"><span class="glyphicon glyphicon-log-out"></span> 註冊</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> {% endblock %} {% block content %} {#定義屬於本身的block#} {% block newcontent %} {% endblock %} {% block footer %} <div class="footer"> 宇宙大魔王--ZAJ </div> {% endblock %} {% endblock %}
Jinja2 中的 extends 指令從 Flask-Bootstrap 中導入 bootstrap/base.html,從而實現模版繼承。Flask-Bootstrap 中的基模版提供了一個網頁框架,引入了 Bootstrap 中的全部 CSS 和 JavaScript 文件。sql
上面這個示例從新定義了3個塊,分別是對 bootstrap/base.html的styles、navbar和content的改寫。這些塊都是基模版提供的,可在衍生模版中從新定義。數據庫
若是程序須要向已經有內容的塊中添加新內容, 必須使用 Jinja2 提供的 super() 函數。例如,若是要在衍生模版中添加新的 CSS 文件,須要這麼定義:flask
{% block styles %} {{ super() }} <link rel="stylesheet" href="../static/css/main.css"> {% endblock %}
要求:bootstrap
實現網頁主頁顯示、登錄頁面顯示、註冊頁面顯示、用戶退出(註銷)。而且只有數據庫中存在用戶能夠登錄網頁。主要經過表單來實現數據交互。目前,對於用戶註冊,不返回數據庫。
實現數組
模板文件有templates/base.html , templates/index.html , templates/login.html , templates/register.html Py文件有 zaj_run.py , zaj_ forms.py , zaj_modles.py , zaj_config.py
模板文件連接
連接:https://pan.baidu.com/s/1Uov-i8b2fZMr9fOe32tcgg 提取碼:jrbs
# zaj_run.py from flask import Flask,render_template,session,redirect,url_for from flask_bootstrap import Bootstrap from zaj_forms import LoginForm,RegisterFrom from zaj_models import isPasswdOk import functools app = Flask(__name__) app.config['SECRET_KEY'] = 'SHEEN' bootstrap = Bootstrap(app) def is_login(f): """判斷用戶是否登錄的裝飾器""" @functools.wraps(f) def wrapper(*args, **kwargs): # 主函數代碼裏面, 若是登錄, session加入user, passwd兩個key值; # 主函數代碼裏面, 若是註銷, session刪除user, passwd兩個key值; # 若是沒有登錄成功, 則跳轉到登錄界面 if 'user' not in session: return redirect('/login/') # 若是用戶是登錄狀態, 則訪問哪一個路由, 就執行哪一個路由對應的視圖函數; return f(*args, **kwargs) return wrapper @app.route('/') def index(): return render_template('index.html') @app.route('/login/',methods=['GET','POST']) def login(): # session.pop('user',None) # session.pop('passwd',None) form = LoginForm() print(form.data) #{'user': 'root123', 'passwd': 'sheen123', 'submit': True,....} if form.validate_on_submit(): user = form.data['user'] passwd = form.data['passwd'] if isPasswdOk(user,passwd): session['user'] = user session['passwd'] = passwd return redirect(url_for('index')) else: return render_template('login.html',form=form,message='密碼或用戶名錯誤') else: return render_template('login.html',form=form) @app.route('/register/',methods=['GET','POST']) def register(): form = RegisterFrom() # 若是是post方法而且表單驗證經過的話, 返回True; if form.validate_on_submit(): # 用戶提交的表單信息 print(form.data) return 'ok' return render_template('register.html', form=form) @app.route('/logout/') def logout(): session.pop('user', None) session.pop('passwd', None) # 註銷即刪除用戶的session信息, 註銷成功, 跳轉到首頁; return redirect(url_for('index')) # return redirect('/') if __name__ == '__main__': app.run( port = 8900) # 報錯1:TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given # 解決:把輸入表單LoginForm,RegisterFrom中的Required去掉 # 問題2:每次從新運行程序,都會顯示root123用戶已登錄,即session裏面有數據 # 解決:添加判別session內容的函數is_login()。
# zaj_models.py,存放數據庫操做 import pymysql from zaj_config import DB # 1. 建立鏈接 conn = pymysql.connect( host=DB.HOST, user = DB.USER, passwd = DB.PASSWD, port = DB.PORT, db = DB.DBNAME, ) cur = conn.cursor() def isUserExist(username): """判斷用戶名是否存在""" sqli = "select * from user where name='%s'" %(username) res = cur.execute(sqli) # res返回的是sql語句查詢結果的個數; # 若是爲0, 沒有查到。 if res == 0: return False else: return True def isPasswdOk(username, passwd): sqli = "select * from user where name='%s' and passwd='%s'" %( username, passwd) res = cur.execute(sqli) if res == 0 : return False else: return True def addUser(username, passwd): """用戶註冊時, 添加信息到數據庫中""" sqli = "insert into user(name, passwd) values('%s', '%s')" %( username, passwd) try: res = cur.execute(sqli) conn.commit() except Exception as e: conn.rollback() return e # # cur.close() # conn.close() if __name__ == "__main__": addUser('root', 'root') print(isUserExist('root')) print(isPasswdOk('root', 'root'))
# zaj_forms.py,存放表單操做 from flask_wtf import FlaskForm # 每一個Web表單都由一個繼承自FlaskForm的類表示 from wtforms import StringField,PasswordField,SubmitField # StringField類表示的是屬性爲type="text"的<input>元素。 # SubmitField類表示的是是屬性爲type="submit"的<input>元素 #WTForms內建的驗證函數validators,並且是以數組形式,正對應了前面說的一個字段能夠有一個或者多個驗證函數 from wtforms.validators import Length, Required, EqualTo, Regexp,Email class LoginForm(FlaskForm): user = StringField( label='用戶名', validators=[ Length(5,13) ] ) passwd = PasswordField( label='密碼', validators=[ Length(6,12), ] ) submit = SubmitField( label='登錄' ) class RegisterFrom(FlaskForm): user = StringField( label='用戶名/郵箱/手機號', validators=[ Length(5,13) ] ) passwd = PasswordField( label='密碼', validators=[ Length(6,12), ] ) repasswd = PasswordField( label='確認密碼', validators=[ EqualTo('passwd',message='密碼不一致!') ] ) phone = StringField( label='電話號碼', validators=[ Regexp(r'1\d{10}', message='手機號碼格式錯誤') ] ) email = StringField( label='郵箱', validators=[ Email(message='郵箱格式錯誤!') ] ) submit = SubmitField( label='註冊' )
# zaj_config.py , 存放數據庫類 class DB: HOST = 'localhost' USER= 'root' PASSWD = 'sheen' PORT = 3306 DBNAME = 'zaj_form'
確保數據庫zaj_form中已有表user,user有元素name,passwd,添加用戶name= ‘python’ , passwd=’1234567’
主頁:
登錄以後,自動跳轉主頁,顯示session的緩存。
當註冊表單某一項不知足程序定義的規則時
當註冊成功時,返回'OK'