实战一:留言板
参考:Flask Web开发实战:入门、进阶与原理解析 中的留言板项目。
在它的基础上添加了mysql 数据库支持,和分页功能。

表结构:

CREATE TABLE `message` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `body` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `timestamp` datetime NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
源码:
FlaskDemo.py
from flask import Flask,url_for,request,render_template,flash,redirect from werkzeug.routing import BaseConverter from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileRequired, FileAllowed from wtforms import SubmitField # 数据库orm from flask_sqlalchemy import SQLAlchemy # UI类 from flask_bootstrap import Bootstrap #国际化日期类 from flask_moment import Moment from datetime import datetime import time import os app = Flask(__name__) ###################################################################### # 留言板 运行环境配置 #配置数据库链接 app.config['SQLALCHEMY_DATABASE_URI'] ='mysql+pymysql://root:root@127.0.0.1:3306/mydb3' #配置数据库出错不需要单独记录,如果做单独记录,就选true app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 数据库初始化,UI初始化,时间类、模板格式初始化 db = SQLAlchemy(app) bootstrap = Bootstrap(app) moment = Moment(app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True ##################################################################### # 留言板数据库ORM模型 #设计orm类,跟mysql的表结构一一对应。 class Message(db.Model): __tablename__ = 'message' #表名称 id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20)) body = db.Column(db.String(200)) timestamp = db.Column(db.DateTime, default=datetime.utcnow, index=True) ################################################################## # 留言板form表单处理逻辑 from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, TextAreaField from wtforms.validators import DataRequired, Length class HelloForm(FlaskForm): name = StringField('Name', validators=[DataRequired(), Length(1, 20)]) body = TextAreaField('Message', validators=[DataRequired(), Length(1, 200)]) submit = SubmitField() ####################################################################################### #留言板视图分页路由 @app.route('/paginate/',methods=['GET', 'POST']) @app.route('/paginate/<int:page>') def message_list(page=1): # 最新的时间排在最前面,直接调用flask写好的分页函数,配置页数,每页几条数据。 messages= Message.query.order_by(Message.timestamp.desc()).paginate(page=page, per_page=3,error_out=False) #form 表单处理逻辑,当表单有post提交的时候,接收过来提交的数据,通过orm类存导mysql中,并返回当前url。 # 没有表单的提交操作,直接返回 form = HelloForm() if form.validate_on_submit(): name = form.name.data body = form.body.data message = Message(body=body, name=name) db.session.add(message) db.session.commit() flash('Your message have been sent to the world!') return redirect(url_for('message_list')) return render_template('index_list.html',form=form,messages=messages.items,pagination=messages) ############################################################################################# if __name__ == '__main__': app.run(debug=1)
分页导航:page.html
{% macro my_paginate(pagination,url) %} <nav> <ul class="pagination"> {%if pagination.has_prev%} <li class="page-item active"><a class="page-link" href="{{url_for(url,page=pagination.page-1)}}">上一页</a></li> {%else%} <li class="page-item disabled"><a class="page-link" href="#">上一页</a></li> {%endif%} {%for page in pagination.iter_pages(1,1,3,1)%} {%if page%} <li class="page-item {%if page==pagination.page%}active{%endif%}"><a class="page-link" href="{{url_for(url,page=page)}}">{{page}}</a></li> {%else%} <li class="page-item disabled"><a class="page-link" href="#">…</a></li> {%endif%} {%endfor%} {%if pagination.has_next%} <li class="page-item active"><a class="page-link" href="{{url_for(url,page=pagination.page+1)}}">下一页</a></li> {%else%} <li class="page-item disabled"><a class="page-link" href="#">下一页</a></li> {%endif%} </ul> </nav> {%endmacro%}
主页显示页面'index_list.html
{% extends 'base.html' %} {% from 'bootstrap/form.html' import render_form %} {% import 'pages.html' as pg%} <!-- 引入分页导航 --> {% block content %} <div class="hello-form"> {{ render_form(form, action=request.full_path) }} </div> <h5>{{ messages|length }} messages <small class="float-right"> <a href="#bottom" title="Go Bottom">↓</a> </small> </h5> <div class="list-group"> {% for message in messages %} <a class="list-group-item list-group-item-action flex-column"> <div class="d-flex w-100 justify-content-between"> <h5 class="mb-1 text-success">{{ message.name }} <small class="text-muted"> #{{ loop.revindex }}</small> </h5> <small data-toggle="tooltip" data-placement="top" data-timestamp="{{ message.timestamp.strftime('%Y-%m-%dT%H:%M:%SZ') }}" data-delay="500"> {{ moment(message.timestamp).fromNow(refresh=True) }} </small> </div> <p class="mb-1">{{ message.body }}</p> </a> {% endfor %} </div> <!-- 引入分页导航--> <div class="pagination" {{pg.my_paginate(pagination,'message_list')}} </div> {% endblock %}