from flask importFlaskimportpymysqlimporttimefrom DBUtils.PooledDB importPooledDB, SharedDBConnection#创建共享连接池
POOL =PooledDB(
creator=pymysql, #使用链接数据库的模块
maxconnections=6, #连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, #初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, #链接池中最多闲置的链接,0和None不限制
maxusage=None, #一个链接最多被重复使用的次数,None表示无限制,连接使用次数过多会有缓存,有时需要使用最新的
setsession=[], #开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
maxshared=3,#链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
blocking=True, #连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
ping=0,#ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host='127.0.0.1',
port=3306,
user='root',
password='',
database='yk2012',
charset='utf8',
)#记忆方法#模块 最大 初始化#闲置 最新 开始化#阻塞 检查 基本化
defget_conn():"""连接数据库
:return: conn, cursor"""conn= POOL.connection() #数据库连接
cursor = conn.cursor(pymysql.cursors.DictCursor) #数据库指针
returnconn, cursordefreset_conn(conn, cursor):""":param conn: 数据库连接
:param cursor: 数据库指针
:return: Null"""cursor.close()
conn.close()deffetch_all(sql, args):""":param sql: sql语句
:param args: sql语句的参数
:return: 查询结果"""conn, cursor=get_conn()
cursor.execute(sql, args)
result=cursor.fetchall()
reset_conn(conn, cursor)returnresult
app=Flask(__name__)
@app.route('/')defindex():
res=fetch_all("select * from student",())print(res)return "执行成功"
if __name__ == '__main__':
app.run(debug=True)
DBUtils
总结:配置项记忆方法
# 模块 最大 初始化
# 闲置 最新 开始化
# 阻塞 检查 基本化
二、数据准备
1:创建相应的数据库和数据表
首先,我们创建一个数据库(StudentManage_WTF)。
再创建一个用户表(User){ID:自增,UserName:用户名, Password:密码}
再创建一个学生表(Student){ID:自增, StudentName: 姓名,Age:年龄, Gender:性别}
#创建数据库
create database StudentManage_WTF;#创建用户表
create table User(
ID int primary key auto_increment,
UserName nvarchar(20) notnull,
Password nvarchar(200) notnull
);#初始化管理员
insert into User (UserName,Password) Values('Aaron','1');#创建学生信息表
create table Student(
ID int primary key auto_increment,
StudentName nvarchar(20) notnull,
Age int,
Gender int
);
数据库创建脚本
三、代码结构和MYSQLHelper工具类
1:代码结构
2:帮助类MYSQLHelper
from flask importFlaskimportpymysqlimporttimefrom DBUtils.PooledDB importPooledDB, SharedDBConnectionclassMYSQLHelper(object):def __init__(self, host, port, dbuser, password, database):
self.pool=PooledDB(
creator=pymysql, #使用链接数据库的模块
maxconnections=6, #连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, #初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, #链接池中最多闲置的链接,0和None不限制
maxusage=None, #一个链接最多被重复使用的次数,None表示无限制,连接使用次数过多会有缓存,有时需要使用最新的
setsession=[], #开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
maxshared=3,#链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
blocking=True, #连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
ping=0,#ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host=host,
port=int(port),
user=dbuser,
password=password,
database=database,
charset='utf8',
)defget_conn(self):"""连接数据库
:return: conn, cursor"""conn= self.pool.connection() #数据库连接
cursor = conn.cursor(pymysql.cursors.DictCursor) #数据库指针
returnconn, cursordefreset_conn(self,conn, cursor):""":param conn: 数据库连接
:param cursor: 数据库指针
:return: Null"""cursor.close()
conn.close()deffetch_all(self,sql, args):""":param sql: sql语句
:param args: sql语句的参数
:return: 查询结果"""conn, cursor=self.get_conn()
cursor.execute(sql, args)
result=cursor.fetchall()
self.reset_conn(conn, cursor)returnresultdefinsert_one(self,sql,args):
conn,cursor=self.get_conn()
res=cursor.execute(sql,args)
conn.commit()
self.reset_conn()returnresdefupdate(self,sql,args):
conn,cursor=self.get_conn()
result=cursor.execute(sql,args)
conn.commit()
self.reset_conn()return result
MYSQLHelper.py
四、WTForm实现登录校验
1:登录页面
a:使用数据库中User表判断是否有权限。
b:使用WTForm框架做校验。
#1:安装WTForms!ps:别安装错了,不是WTForm
from wtforms.fields importsimple,corefrom wtforms importForm,validators,widgetsclassLoginForm(Form):
username=simple.StringField(
label="用户名",
validators=[
validators.data_required(message="用户名不能为空")
],
widget=widgets.TextInput(),
render_kw={"class":"my_username"}
)
password=simple.StringField(
label="密码",
validators=[
validators.data_required(message="密码不能为空!")
],
widget=widgets.PasswordInput()
)
submit=simple.SubmitField(
label="提交")
ModelForm
{% extends "index.html" %}
{% block css %}
display: none
}{% endblock %}
{% block content %}
学生登录
{% for filed in loginForm %}{{ filed.label }} {{ filed }}{{ filed.errors.0 }}
{% endfor %}{% endblock %}s_login.html
from flask importBlueprintfrom flask importrender_template, request, session, redirectfrom StudentManage_WTF.Tools.Helper.DBHelper.MYSQLHelper importMYSQLHelperfrom StudentManage_WTF.UserLogin.ModelForm.LoginModel importLoginForm#每个蓝图都可以为自己独立出一套template模板文件夹,如果不写则共享项目目录中的templates
sl = Blueprint("sl", __name__, template_folder="templates")
@sl.route("/s_login", methods=("GET", "POSt"))defuserLogin():if request.method == "GET":
loginForm=LoginForm()return render_template("s_login.html", loginForm=loginForm)else:
lf=LoginForm(request.form)iflf.validate():
username= request.form.get("username")
password= request.form.get("password")#获取sql帮助类对象
sqlhelper = MYSQLHelper("127.0.0.1", 3306, "root", "", "StudentManage_WTF")#拼接sql语句
sql = "select id,username from user where username='%s' and password='%s'" %(username, password)
res=sqlhelper.fetch_all(sql, ())print(res)ifres:
session["user"] =resreturn redirect("/s_view")else:
session["user"] =None
lf.username.errors.append("用户名或密码错误!")return render_template("s_login.html", loginForm=lf)else:return render_template("s_login.html", loginForm=lf)
login.py
五、学生信息的维护
1:学生列表页面
from flask importBlueprintfrom flask importrender_templatefrom StudentManage_WTF.Tools.Helper.DBHelper.MYSQLHelper importMYSQLHelper#每个蓝图都可以为自己独立出一套template模板文件夹,如果不写则共享项目目录中的templates
sv = Blueprint("sv", __name__, template_folder="templates")
@sv.route("/s_view")defstudentView():#获取sql帮助类对象
sqlhelper = MYSQLHelper("127.0.0.1", 3306, "root", "", "StudentManage_WTF")#拼接sql语句
sql = "select * from Student where 1=1"studentList=sqlhelper.fetch_all(sql, ())return render_template("s_view.html", studentList=studentList)
s_view.py
{% extends "index.html" %}
{% block content %}
学生列表
编号 学生姓名 年龄 性别 操作 {{ student.ID }} {{ student["StudentName"] }} {{ student.get("Age") }} {{ student.Gender }} 修改 | 删除 {% endfor %}新增{% endblock %}
s_view.html
2:学生管理页面
from flask importBlueprintfrom flask importrender_template, request, redirectfrom StudentManage_WTF.student_oper.ModelForm.StudentModel importStudentFormfrom StudentManage_WTF.configer.MYSQLSetting importgetMYSQLHelper#每个蓝图都可以为自己独立出一套template模板文件夹,如果不写则共享项目目录中的templates
sa = Blueprint("sa", __name__, template_folder="templates")
sqlhelper=getMYSQLHelper()
@sa.route("/s_add", methods=('GET', 'POST'))defstudentAdd():if request.method == "GET":
stu=StudentForm()return render_template("s_add_modify.html", curTitle="新增", curAction="/s_add", stu=stu)else:
stu=StudentForm(request.form)ifstu.validate():#获取sql帮助类对象
#拼接sql语句
sql = "insert into student (studentname,age,gender) values('%s',%s,%s);" %(
stu.StudentName.data, stu.Age.data, stu.Gender.data)
res=sqlhelper.insert_one(sql, ())return redirect("/s_view")else:return render_template("s_add_modify.html", curTitle="新增", curAction="/s_add", stu=stu)
@sa.route("/s_update/", methods=('GET', 'POST'))defstudentUpdate(id):if request.method == "GET":
sql= "select * from student where ID='%s'" %(id)
curStu=sqlhelper.fetch_all(sql, ())ifcurStu:
curStu= StudentForm(**curStu[0]) #神来之笔
return render_template("s_add_modify.html", curTitle="编辑", curAction="/s_update/" + str(id), stu=curStu)else:
stu=StudentForm(request.form)ifstu.validate():
sql= "update student set studentname='%s',age='%s',gender='%s' where ID='%s'"\%(stu.StudentName.data, stu.Age.data, stu.Gender.data, id)
res=sqlhelper.update(sql, ())return redirect("/s_view")else:return render_template("s_add_modify.html", curTitle="编辑", curAction="/s_update/" + str(id), stu=stu)
@sa.route("/s_del", methods=('GET', 'POST'))defstudentDel():
id= request.args.get('id')
sql= "delete from student where ID='%s'" %(id)
curStu=sqlhelper.update(sql, ())return redirect("/s_view")
s_add_modify_del.py方法
from wtforms.fields importsimple, corefrom wtforms importwidgets, validators, FormclassStudentForm(Form):
ID=simple.StringField(
widget=widgets.HiddenInput
),
StudentName=simple.StringField(
label="姓名",
validators=[
validators.data_required(message="学生姓名不能为空!"),
validators.Length(min=2, max=20, message="学生姓名长度必须大于2位,小于20位")
]
)
Age=core.StringField(
label="年龄",
validators=[
validators.data_required(message="学生年龄不能为空!"),
validators.Regexp(regex="^\d+$", message="学生年龄必须为数字")
]
)
Gender=core.RadioField(
label="性别",
coerce=int, #保存到数据中的值为int类型
choices=(
(0,'女'), (1, '男')
),
default=1)
submit=simple.SubmitField(
label="提交")
StudentModel
{% extends "index.html" %}
{% block css %}
display: none
}{% endblock %}
{% block content %}
学生{{ curTitle }}
{% for filed in stu %}{{ filed.label }} {{ filed }}{{ filed.errors.0 }}
{% endfor %}{% endblock %}s_add_modify.html