点击名片关注 阿尘blog,一起学习,一起成长
1 使用Flask-Bootstap集成Bootstrap
Bootstrap是Twitter开发的一个开源的Web框架,提供了用户界面组件可用于创建整洁且具有吸引力的网页,兼容桌面和移动Web,flask要集成Bootstrap就要利用flask的拓展:Flask-Bootstrap
安装flask-bootstrap
pip install flask-bootstrap
初始化Bootstrap
from flask import Flask
from flask_bootstrap import Bootstrap
app = Flask(__name__)
# 初始化bootstrap
bootstrap = Bootstrap(app)
@app.route('/index')
def index():
return render_template('index.html',name='阿尘')
index.html
{% extends "bootstrap/base.html" %}
{% block title %}Flask-Bootstrap Example{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-target=".navbar-collapse">
<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="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
<h1>Hello,{{ name }}</h1>
</div>
</div>
{% endblock %}
在jinja2中,extend指令从flask-bootstrap中导入bootstrap/base.html从而实现模板的继承 在index模板中我们定义了三个区块,title、navbar、content
如果要在衍生模板中使用新的JavaScript文件那么需要如下定义新的scripts区块
{% block scripts %}
{{ super() }}
<scripts type="text/javascript" src="your-own-script.js"></scripts>
{% endblock %}
当然你也可以自己定义一个二级基础模板放在templates里面
{% extends "bootstrap/base.html" %}
{% block title %}Flask-Bootstrap Example{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-target=".navbar-collapse">
<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="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
有了这个模板我们可以不用直接继承flask-bootstrap的基模板,而用这个来自定义其他页面,比如404页面
{% extends 'base.html' %}
{% block title %}Flasky- Page Not Found{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Not Found</h1>
</div>
{% endblock %}
2 使用Flask-Moment本地化日期和时间
web应用的用户如果来自世界各地,处理时间就是一个复杂的任务,一般使用协调世界时间(UTC)再把UTC转化为用户习惯的当地时间格式,要做到这样可以把时间单位发给web然后采用JavaScript渲染。
有一个JavaScript开发的客户端开源库:Moment.js,可以对浏览器的日期和时间进行渲染,而Flask的一个扩展,Flask-Moment就简化了Moment.js集成到了Jinja2模板中的过程
安装Flask-Moment
pip install flask-moment
初始化Flask-Moment
from flask_moment import Moment
from flask import Flask
app = Flask(__name__)
moment = Moment(app)
然后在templates/base.html引入Moment.js库,放在任何位置都可以
{% endblock %}
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
然后修改app.py
from datetime import datetime
@app.route('/index')
def index():
return render_template('index.html',current_time=datetime.utcnow())
渲染index.html
{% block content %}
<div class="container">
<p>当地日期和时间为{{ moment(current_time).format('LLL') }}.</p>
<p>当前页面停留{{ moment(current_time).fromNow(refresh=True) }}</p>
</div>
{% endblock %}
format()函数的L代表时间复杂程度
第二行是会随着时间推移刷新
具体还有其他方法,可以参考官网
渲染的时间还可以切换不同语言,这需要在引入momen.js,将语言代码传给locale()函数
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{{ moment.locale('zh-CN') }}
{% endblock %}
3 Web表单
之前在第四篇分享文章中,实现登录页面,里面有使用表单,但是那是我直接在html模板文件中创建的表单,flask-wtf扩展集成WTForms,支持在Python中使用类定义表单,然后直接通过类定义生成对应的HTML代码,这种方式更加方便,而且使表单更易于重用。
安装flask-wtf
pip install flask-wtf
为了防治表单遭到攻击,flask-wtf要求应用配置一个秘钥
app.secret_key = 'secret string'
表单类:在用flask-wtf时,每个web表单都有一个继承自FlaskForm的类表示,这个类定义了表单中的一组字段,每个字段都用对象表示,字段还可以复数一个或多个验证码函数用于验证用户提交的数据是否 有效:下面WebForm.py
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField,PasswordField,BooleanField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired(), Length(6, 18)])
remember = BooleanField('Remember me')
submit = SubmitField('Log in')
WTForms支持的HTML标准字段
通过实例化字段类时传入的参数,我们可以对字段进行设置,字段类构造方法接收的常用参数如表
在WTForms
中,验证器(validator)
是一系列用于验证字段数据的类,我们在实例化字段类时使用validators关键字来指定附加的验证器列表。验证器从wtforms.validators
模块中导入,常用的验证器如表:
验证器的第一个参数一般为错误提示消息,我们可以使用message
关键字传递参数,通过传入自定义错误信息来覆盖内置消息
创建完表单类,我们就可调用来获取对应HTML代码
from webForm import LoginForm # 导入写的表单类
from flask import Flask,render_template,redirect,url_for
import secrets
app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
# 实例化表单
login_form = LoginForm()
return render_template('login.html',form = login_form)
在模板中渲染表单:login.html,Bootstrap风格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Page</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk5gwnNi8nXn50KGpyuVoXckpaBVifq0Ei7gykkjaj温xkfa90" crossorigin="anonymous">
</head>
<body>
<form method="post" class="container-lg">
{{ form.csrf_token }}
<div class="form-group">
{{ form.username.label }}
{{ form.username(class='form-control') }}
</div>
<div class="form-group">
{{ form.password.label }}
{{ form.password(class='form-control') }}
</div>
<div class="form-check">
{{ form.remember(class='form-check-input') }}
{{ form.remember.label }}
</div>
{{ form.submit(class='btn btn-primary') }}
</form>
</body>
</html>
处理表单,在视图函数中处理表单
@app.route('/login',methods=['GET','POST'])
def login():
# 实例化表单
login_form = LoginForm()
if login_form.validate_on_submit():
if login_form.username == 'jonas' and login_form.password == 'a123456':
flash(f'登陆成功,欢迎用户{login_form.username}!',category='success')
return redirect(url_for('welcome'))
else:
flash('登录失败!请重新登陆')
return redirect(url_for('login'))
return render_template('login.html',form = login_form)
@app.route('/welcome')
def welcome():
return 'Welcome!'
如上通过对前端传回的请求进行处理判断,而在这个视图中我们添加了闪现消息,闪现消息也就是常见的弹窗提示,通过flash()函数发送消息,flash()函数有两个参数,一个是message字段(必填),一个是类别字段(选填),flash推送的消息是由数组组成的列表,所以也可以循环
闪现消息的模板渲染:
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class="container-lg">
{% for category ,message in messages %}
{% if category == 'success' %}
<div class="alert-success">{{ message }}</div>
{% else %}
<div class="alert-warning">{{ message }}</div>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endwith %}
这里面的样式我同样采用的上述bootstrap.css进行渲染
实际效果
扫描二维码关注阿尘blog,一起交流学习