python表单管理系统_饮冰三年-人工智能-Python-42 Python之Flask中的WTForm+DBUtils实现学生管理系统...

1126880-20200108205219930-261464319.png

ContractedBlock.gif

ExpandedBlockStart.gif

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:性别}

ContractedBlock.gif

ExpandedBlockStart.gif

#创建数据库

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:代码结构

1126880-20200109132026609-1859150211.png

2:帮助类MYSQLHelper

ContractedBlock.gif

ExpandedBlockStart.gif

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框架做校验。

ContractedBlock.gif

ExpandedBlockStart.gif

#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

ContractedBlock.gif

ExpandedBlockStart.gif

{% 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

ContractedBlock.gif

ExpandedBlockStart.gif

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

1126880-20200109141950850-1494828584.png

五、学生信息的维护

1:学生列表页面

ContractedBlock.gif

ExpandedBlockStart.gif

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

ContractedBlock.gif

ExpandedBlockStart.gif

{% extends "index.html" %}

{% block content %}

学生列表

编号

学生姓名

年龄

性别

操作

{{ student.ID }}

{{ student["StudentName"] }}

{{ student.get("Age") }}

{{ student.Gender }}

修改 | 删除

{% endfor %}

新增{% endblock %}

s_view.html

1126880-20200109150102936-1686183089.png

2:学生管理页面

ContractedBlock.gif

ExpandedBlockStart.gif

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方法

ContractedBlock.gif

ExpandedBlockStart.gif

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

ContractedBlock.gif

ExpandedBlockStart.gif

{% 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

1126880-20200109172137712-416536229.png

1126880-20200109172111541-1394591886.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值