本篇接着《Flask 极简 CRUD 操作》继续讲解怎样让页面变得漂亮。在《Flask 极简 CRUD 操作》中,我们实现了基本的 CRUD 操作,如果运行一下,我们发现页面长得像这个样子:
我们可以使用 Bootstrap 这个著名的前端框架,让 web 的开发更迅速和简单。回忆一下,我们当时写的 index.html
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Basic CRUD</title>
<link rel="stylesheet" type="text/css" href="../static/styles.css">
</head>
<body>
<a href="{{ url_for('notesbp.new_note') }}">New note</a>
<h4> {{ notes|length }} Notes: </h4>
<table>
<tr>
<th>ID</th>
<th>Body</th>
<th>Action</th>
</tr>
{% for note in notes %}
<tr>
<td> {{note.id}} </td>
<td> {{note.body}} </td>
<td>
<a href="{{ url_for('notesbp.edit_note', note_id=note.id) }}">Edit</a>
<a href="{{ url_for('notesbp.delete_note', note_id=note.id) }}">Delete</a>
</td>
</tr>
{% endfor %}
</table>
</body>
</html>
使用 Bootstrap 美化这个界面需要两步:
- 页面引用 Bootstrap 依赖文件(css, javascript代码),我们甚至不用下载,直接使用网络上的 CDN 服务。依赖文件见下面的示例
- 设置 HTML 标签的 class 属性
引用四个依赖文件
<!-- 新 Bootstrap4 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<!-- popper.min.js 用于弹窗、提示、下拉菜单 -->
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
国内推荐使用 : https://www.staticfile.org/, 国际推荐使用:https://cdnjs.com/
设置标签的 class 属性
将 index.html 页面中 table
和 button
的 class
属性为 Bootstrap 预设类别,瞬间即可美颜。index.html 代码变更如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Basic CRUD</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<a class="btn btn-primary" href="{{ url_for('notesbp.new_note') }}">New note</a>
<table class="table table-hover">
<tr>
<th>ID</th>
<th>Body</th>
<th>Action</th>
</tr>
{% for note in notes %}
<tr>
<td> {{note.id}} </td>
<td> {{note.body}} </td>
<td>
<a class="btn btn-primary btn-sm" href="{{ url_for('notesbp.edit_note', note_id=note.id) }}">Edit</a>
<a class="btn btn-primary btn-sm" href="{{ url_for('notesbp.delete_note', note_id=note.id) }}">Delete</a>
</td>
</tr>
{% endfor %}
</table>
</body>
</html>
再来看看页面,变成了下面的样子:
将引用依赖移入 base.html
Flask 的模版继承让我们从多个页面引用相同的内容变得简单。既然其他页面也要使用这些依赖,我们不妨放在 base.html
文件中。在 templates
文件夹下面新建一个 base.html
文件,编写代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
{% block body_content %}
{% endblock %}
</body>
</html>
base.html
模版文件中定义了一个 body_content
块,其他 html 文件可以从 base.html
文件继承,并且实现 body_content
块就可以了。将 index.html
进行改造,改造后的文件代码如下:
{% extends 'base.html' %}
{% block body_content %}
<div>
<a href="{{ url_for('notesbp.new_note') }}" class="btn btn-primary">New note</a>
</div>
<table class="table table-hover">
<tr>
<th>ID</th>
<th>Body</th>
<th>Action</th>
</tr>
{% for note in notes %}
<tr>
<td> {{note.id}} </td>
<td> {{note.body}} </td>
<td>
<a class="btn btn-primary btn-sm" href="{{ url_for('notesbp.edit_note', note_id=note.id) }}">Edit</a>
<a class="btn btn-primary btn-sm" href="{{ url_for('notesbp.delete_note', note_id=note.id) }}">Delete</a>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
此时界面效果与之前完全相同。
使用 Flask-Bootstrap
前面代码我们使用 Bootstrap 框架来美化界面,并没有用到 Flask-Bootstrap。那么 Flask-Bootstrap 的作用又是什么呢?简单的来说:
- 自动引用 CDN
- 可以与 WTForm 或其他 Flask 插件比如 Flask-nav 一起使用
安装 Flask-Bootstrap:
pip install flask-bootstrap
关联 Flask app
from flask_bootstrap import Bootstrap
Bootstrap(app)
使用 Flask-Bootstrap 渲染 WTF Form
以 edit_form.html
为例,之前的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Edit Note</title>
</head>
<body>
<h2>Edit Note</h2>
<form method="POST">
{{ form.body(rows='10',cols='100') }}<br/>
{{ form.submit }}
</form>
</body>
</html>
其中 Form 中的字段是通过 WTForm 传入的,对这些字段如何套用 Bootstrap 的样式呢?
- 引用 Flask-Bootstrap 的
wtf.html
文件
{% import 'bootstrap/wtf.html' as wtf %}
- 调用
wtf.form_field()
表单宏:
{{ wtf.form_field(some_field) }}
经过改写的 edit_form.html
如下:
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block body_content %}
<h2>Edit Note</h2>
<form class="form" method="POST">
{{ wtf.form_field(form.body) }}
{{ wtf.form_field(form.submit) }}
</form>
{% endblock %}
自定义表单样式
对于表单的样式,比如希望输入 body 的时候有多行,有两种定义方法。方法一是在定义 Form 字段的时候,传入一个 render_kw
参数,这个参数为 dict 类型,如下面这样:
class EditNoteForm(Form):
body = TextAreaField('body', render_kw={'class': 'text-body', 'rows': 10, 'placeholder': '输入您的想法...'})
submit = SubmitField('Update')
方法二是在渲染时控制样式:
{{ wtf.form_field(form.body, , class="text-body", rows="10")) }}
本文源码
源码托管在 Github
网友评论