个人拙见,web 后端就是一个对数据库进行 CRUD (增删改查)的操作过程。
本章内容就是基于 flask 这个前后端一体化的架构,使用 flask-wtf 插件,打通前后端的联系,来讲解一下 CRUD 操作。
配置 flask 项目
参照 你应该会玩儿 flask的前几章教程,使用大型项目的结构即蓝图模式来配置项目。
项目结构如下:
flask-wtf-crud/
|-- env/
|--
|-- app/ <项目的模块名称>
|-- crud/ <前端蓝图>
|-- __init__.py
|-- views.py <路由和视图函数文件>
|-- forms.py <表单类文件, wtforms插件必须项>
|-- templates
|-- static <静态文件夹>
|-- XXXXXX/ <其它蓝图>
|-- __init__.py
|-- models.py <数据库模型文件>
|-- migrations/ <数据库表关系文件夹,Flask-Migrate迁移数据库时使用>
|-- config.py <项目的配置文件>
|-- manage.py <用于启动程序以及其它程序任务>
对于 crud 蓝图的配置,不再赘述,如果想了解,可以查看源码。
作品内容:
配置数据库示例
创建一个 User 数据库字段。
# -*- coding:utf-8 -*-
__author__ = '东方鹗'
__blog__ = u'http://www.os373.cn'
from . import db
class User(db.Model):
'''Example for crud
以用户为例,来展示 CRUD 操作!
'''
__tablename__ = 'crud'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
email = db.Column(db.String(64), unique=True, index=True)
status = db.Column(db.Boolean, default=False)
role = db.Column(db.Boolean, default=False)
def __repr__(self):
return '' % self.username
创建视图函数 views.py
# -*- coding:utf-8 -*-
__author__ = '东方鹗'
__blog__ = u'http://www.os373.cn'
from flask import render_template, redirect, request, current_app, url_for, flash
from . import crud
from ..models import User
from .forms import AddUserForm, DeleteUserForm, EditUserForm
from ..import db
@crud.route('/basic', methods=['GET', 'POST'])
def basic():
add_user_form = AddUserForm(prefix='add_user')
delete_user_form = DeleteUserForm(prefix='delete_user')
if add_user_form.validate_on_submit():
if add_user_form.role.data == u'True':
role = True
else:
role = False
if add_user_form.status.data == u'True':
status = True
else:
status = False
u = User(username=add_user_form.username.data.strip(), email=add_user_form.email.data.strip(),
role=role, status=status)
db.session.add(u)
flash({'success': u'添加用户<%s>成功!' % add_user_form.username.data.strip()})
if delete_user_form.validate_on_submit():
u = User.query.get_or_404(int(delete_user_form.user_id.data.strip()))
db.session.delete(u)
flash({'success': u'删除用户<%s>成功!' % u.username})
users = User.query.all()
return render_template('basic.html', users=users, addUserForm=add_user_form,
deleteUserForm=delete_user_form)
@crud.route('/basic-edit/', methods=['GET', 'POST'])
def user_edit(user_id):
user = User.query.get_or_404(user_id)
edit_user_form = EditUserForm(prefix='edit_user', obj=user)
if edit_user_form.validate_on_submit():
user.username = edit_user_form.username.data.strip()
user.email = edit_user_form.email.data.strip()
if edit_user_form.role.data == u'True':
user.role = True
else:
user.role = False
if edit_user_form.status.data == u'True':
user.status = True
else:
user.status = False
flash({'success': u'用户资料已修改成功!'})
return redirect(url_for('.basic'))
return render_template('edit_basic.html', editUserForm=edit_user_form, user=user)
知识点:
- 视图函数中实现了增加功能和删除功能。
- 多个删除功能也只是需要一个 form 类表单来实现,主要的难点在于前端设计。
- 实现了修改功能的视图函数,初看是一个简单的单 form 表单提交功能而已,但是,请记住这行代码
edit_user_form = EditUserForm(prefix='edit_user', obj=user)
,特别是obj=user
,其中 user 是 User 数据库类的实例,这样的功能将实现修改功能的模板能够显示出原有的实例的内容。
创建 forms.py 表单类
# -*- coding:utf-8 -*-
__author__ = '东方鹗'
__blog__ = u'http://www.os373.cn'
from flask_wtf import Form
from wtforms import StringField, SelectField, SubmitField
from wtforms.validators import DataRequired, Length, Email, Regexp
from wtforms import ValidationError
from ..models import User
class AddUserForm(Form):
username = StringField(u'用户名', validators=[DataRequired(), Length(1, 64, message=u'姓名长度要在1和64之间'),
Regexp(ur'^[\u4E00-\u9FFF]+$', flags=0, message=u'用户名必须为中文')])
email = StringField(u'邮箱', validators=[DataRequired(), Length(6, 64, message=u'邮件长度要在6和64之间'),
Email(message=u'邮件格式不正确!')])
role = SelectField(u'权限', choices=[(u'True', u'管理员'), (u'False', u'一般用户') ])
status = SelectField(u'状态', choices=[(u'True', u'正常'), (u'False', u'注销') ])
submit = SubmitField(u'添加用户')
def validate_username(self, field):
if User.query.filter_by(username=field.data).first():
raise ValidationError(u'用户名已被注册!')
def validate_email(self, field):
if User.query.filter_by(email=field.data).first():
raise ValidationError(u'邮箱已被注册!')
class DeleteUserForm(Form):
user_id = StringField()
class EditUserForm(Form):
username = StringField(u'用户名', validators=[DataRequired(), Length(1, 64, message=u'姓名长度要在1和64之间'),
Regexp(ur'^[\u4E00-\u9FFF]+$', flags=0, message=u'用户名必须为中文')])
email = StringField(u'邮箱', validators=[DataRequired(), Length(6, 64, message=u'邮件长度要在6和64之间'),
Email(message=u'邮件格式不正确!')])
role = SelectField(u'权限', choices=[(u'True', u'管理员'), (u'False', u'一般用户') ])
status = SelectField(u'状态', choices=[(u'True', u'正常'), (u'False', u'注销')])
submit = SubmitField(u'修改用户')
知识点:
- 进行了表单的验证,查看 flask-wtf 官方文档即可。
- 实现了用户名和邮箱的唯一性验证。此处留一个彩蛋,在模板中,我没有实现唯一性的提示功能,你可以自己添加,欢迎留言。
创建前段模板
首先创建 basic.html
加载 bootstrap 前端框架,不再赘述。
basic.html
模板内容
{% extends 'common/base.html' %}
{% block content %}
{% include 'common/alert.html' %}
CRUD 基本示例
序号
用户名
邮箱
权限
状态
{% for user in users %}
{{ loop.index }}
{{ user.username}}
{{ user.email}}
{% if user.role %}
管理员
{% else %}
一般用户
{% endif %}
{% if user.status %}
正常
{% else %}
注销
{% endif %}
修改 |
删除
{% endfor %}
{% endblock %}
知识点:
- 一个页面里有多个 form,包括 modal 里实现的增加功能的 form 和 实现了删除功能的 form。
- 实现了删除功能的 form 并不是单独的存在,二是通过 jinja2 的循环功能,生成了不同 id 的具有删除功能的 form。
- 修改功能是通过另外一个单独的页面实现。
edit_basic.html
模板内容
{% extends 'common/base.html' %}
{% block content %}
{% endblock %}
知识点: 无。参照 flask-wtf 的官方文档即可。
源码下载地址:https://github.com/eastossifrage/flask-wtf-crud/archive/basic.zip
查看原文