flask中mysql的连接以及增删改查数据
flask中连接mysql需要安装进行一下几个步骤:
一、需要安装两个模块
首先,创建一个falsk项目
需要安装pymysql与flask-sqlalchem模块,可通过pip命令进行安装,也可在pycharm的界面进行安装,这里不做演示
二、配置数据库连接
在flask项目下创建一个settings.py文件,并配置数据库的相关参数
settings.py
DEBUG = True # 当处于debug状态时,每修改一次flask中的代码,都会中新reload一次flask项目
# mysql(数据库软件) + pymsql(连接数据库的模块)://数据库用户:密码@ip:端口/库名
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://用户名:密码@IP:端口/数据库名'
SQLALCHEMY_TRACK_MODIFICATIONS = False # 消除警告信息
SQLALCHEMY_ECHO = True
创建一个app目录,为了便于存放管理路由。当项目中路由数过多,全部放在app.py文件不便于管理,最好app.py中只存放启动代码,不同的路由分开存放。我们创建一个app目录就是为了保存管理路由。在app目录下再创建一个users目录,用户管理用户功能的路由。
在users目录中创建一个module.py的文件,文件主要是用于连接数据库,定义mysql数据的表
# 创建一个映射对象
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# ORM 类------表
# 类对象 ------ 表中的记录
from datetime import datetime
class User(db.Model): # 继承db中的Model,这里的类名也是表名
"""
# db.Column(类型, 约束) 映射表中的列
# 类型: 相当与mysql中表字段类型
db.Integer int
db.String(12) vachar(15)
db.DateTime datetime
"""
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), nullable=False) # nullable 表示字段能不能为空
password = db.Column(db.String(64), nullable=False)
phone = db.Column(db.String(11), unique=True)
email = db.Column(db.String(30), nullable=False) # nullable 表示字段不能为空
redatatime = db.Column(db.DateTime, default=datetime.now)
isdelete = db.Column(db.Boolean, default=False) # 用于标志是否删除用户
def __str__(self):
return self.username
在users目录下创建一个view.py的管理路由试图的文件
import hashlib
from operator import or_, and_, not_
from flask import Blueprint, url_for, request, render_template, redirect
from apps.users.module import Easyops, User
from ext import db
user_bp = Blueprint('user', __name__)
# 用户首页,展示
@user_bp.route('/')
def user_center():
users = User.query.filter(User.isdelete == False).all()
# users = User.query.all() # 相当于slect * from 表
print(users) # 返回的为一个列表,列表中存放的为用户对象
# print(url_for('/')) # 反向解析,通过视图找到url,需要先指定: url_for(蓝图.视图函数)
return render_template('user/center.html', users=users)
#print(user_bp.url_values_defaults)
# 用户注册
@user_bp.route('/register', methods= ['GET', 'POST'])
def register():
if request.method == "POST":
username = request.form.get('username')
email = request.form.get('email')
password = request.form.get('password')
reapssword = request.form.get('repassword')
phone = request.form.get('phone')
if password == reapssword:
# 与模型结合,完成数据库的添加
# 1、找到模型类并创建对象
user = User() # 这里需要导入User类,可看import
# 2、为对象赋值
user.username = username
user.password = hashlib.sha256(password.encode('utf-8')).hexdigest()
user.phone = phone
user.email = email
# 添加
# 3、将user对象添加到session中,类似于缓存
db.session.add(user)
# 4、提交数据部分
db.session.commit() # commit成功则表示数据插入成功
return redirect('/')
else:
return "两次密码不一致"
return render_template('user/register.html')
# 用户登录
@user_bp.route('/login', methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
# 关键 select * from user where username = 'xxxx'
nex_password = hashlib.sha256(password.encode('utf-8')).hexdigest() # 生成新的加密密码
# 查询 filter_by相当于sql中的where,返回值为一个列表结构,可能查询到多条数据
# filter_by(xxxx='xxx').first() 代表从列表中取出第一条数据
# filter_by(xxxx='xxx').last() 代表从列表中取出第一条数据
users_info = User.query.filter_by(username=username) # 这里前面的username是user表中的表字段,后面的为对应的值
print(users_info)
for user in users_info:
if user.password == nex_password:
return '用户登录成功'
else:
return render_template('user/login.html', msg='用户名或者密码有误!')
return render_template('user/login.html')
# 查找
@user_bp.route('/search')
def search():
keyword = request.args.get('search')
# 查询
user_info = User.query.filter(or_(User.username.contains(keyword), User.phone.contains(keyword))).all() # 这是查询到的用户数据
return render_template('user/center.html', users=user_info)
# 删除用户
@user_bp.route('/delete')
def delete():
# 从请求中获取到传参id的值
id = request.args.get('id')
# 通过id找到对应的用户,因为id是主键,所以get
id_user = User.query.get(id)
# # 进行逻辑删除
##############################
# 逻辑删除
# id_user.isdelete = True
# db.session.commit()
######################################
# 物理删除
db.session.delete(id_user) # 将对象放到缓存中
db.session.commit() # 提交删除
return redirect(url_for('user.user_center'))
@user_bp.route('/test')
def test():
username = request.args.get('username')
users_info = User.query.filter_by(username=username).first()
print(users_info.username, users_info.phone)
return 'test'
# 检索
@user_bp.route('/select')
def select():
user_info = User.query.get(0) # 根据主键查询用户,使用get(主键值),返回的是一个用户对象
# lu_info = User.query.filter(User.username == 'lu').all() # all()返回一个列表 filer()返回第一条数据
lu_info = User.query.filter(User.username.startswith('lu')).all() # 这里是是以username字段中以lu开头的用户,startswith表示以xx开头
lu_info_end = User.query.filter(User.username.endswith('lu')).all() # 这里是以lu结尾的用户
lu_info_cen = User.query.filter(User.username.contains('lu')).all() # 包含,这里是以usernmae中包含lu的用户
select_info = User.query.filter(or_(User.username.like('l%'), User.username.contains('u'))).all() # 这里是表示查询中表示or
and_info = User.query.filter(and_(User.username.contains('l'), User.redatatime < '2021-03-07 20:35')).all() # 这里是查询表示and
#not_info = User.query.filter(not_(User.username.contains('u'))).all()
user_list = User.query.filter(User.phone.in_(['110', '120'])).all()
# 排序
users_all = User.query.filter(User.username.contains('f')).order_by('redatatime').all() # 这里表示先查询,然后将查询出来的数据通过redatatime字段进行排序,默认惊醒升序排序
user_id = User.query.order_by(User.redatatime).all() # 这里是通过User的redatatime对所有的进行排序,默认进行升序
users_id = User.query.order_by(-User.redatatime).all() # 进行降序,在前面加-
# limit
limit_info = User.query.order_by(User.id).limit(2).all() # 这里是将查询出来的值,limit(2获取前两条记录
limit_info1 = User.query.offset(2).limit(2).all() # offset(2)表示跳过前两条,limit(2)再获取两条记录
return render_template('user/select.html', user_info=user_info, lu_info=lu_info,lu_info_end=lu_info_end,lu_info_cen=lu_info_cen, select_info=select_info, and_info=and_info, user_list=user_list
,users_all=users_all,user_id=user_id,users_id=users_id,limit_info=limit_info, limit_info1=limit_info1)
@user_bp.route('/update', endpoint='update', methods=["GET", "POST"])
def update():
if request.method == "POST":
username = request.form.get('username')
phone = request.form.get('phone')
id = request.form.get('id')
# 通过主键id找到对应的用户
user_info = User.query.get(id)
# 修改用户信息
user_info.phone = phone
user_info.username = username
db.session.commit()
return redirect(url_for('user.user_center'))
else:
user_id = request.args.get('id')
user = User.query.get(user_id)
return render_template('user/update.html', user=user)
在app目录下的__init__.py
from flask import Flask
import settings
from apps.users.module import db
from apps.users.view import user_bp
def create_app():
app = Flask(__name__, template_folder='../templates', static_folder='../static') # 定义模版templates的路径和static路径
app.config.from_object(settings.DevelopmentConfig)
db.init_app(app) # 将db与app进行关联
app.register_blueprint(user_bp) # 注册蓝图1
return app
app.py文件
# encoding: utf-8
from flask_migrate import Migrate,MigrateCommand
from flask_script import Manager
from apps import create_app
# from ext import db
from apps.users.module import Easyops, UserInfo, User, db
app = create_app()
manager = Manager(app=app) # app需要定义,使用先定义的app
# /Users/julie-zhou/flaskProject/bin/python app.py runserver
# 还可以在后面接参数,通过--help查看
# 命令工具
migrate = Migrate(app=app, db=db)
manager.add_command('db', MigrateCommand)
# 自定义命令
@manager.command
def init():
print('初始化!')
if __name__ == '__main__':
manager.run()
三、运行flask项目
在第一次连接数据库时,应当按照一下步骤来进行
注意:init命令只有在第一次连接数据库新建表的时候使用,当修改表时只需要使用migrate和upgrade命令
在终端使用命令:db
python app.py db init # 执行命令后会在项目文件夹中产生一个migrations文件夹,一个项目只需要init一次
再执行命令:db
python app.py db migrate # 会在migrations文件夹下的versions文件夹下生成一个xxxx.py的文件,只要对模型做了任何操作都需要进行migrate
再次执行命令:db
python app.py db upgrade # 就会在mysql对应的数据库中创建表
数据库的连接总结
########################
# 连接数据库 #
########################
1、安装模块
需要装两个模块:pymysql、flask-sqlalchem、
pymysql: 连接数据库
sqlalchem: ORM映射关系
flask-sqlalchem 基于sqlalchem,做了提升
2、配置数据库的连接路径
配置文件setting.py中配置数据库连接
# mysql(数据库软件) + pymsql(连接数据库的模块)://数据库用户:密码@ip:端口/库名
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://easyops:easyops@47.107.229.100:3306/easyops'
3、创建ext包
在__init__.py中添加
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
4、在apps包
在__init__.py的create_app函数中
from ext import db
db.init_app(app) # 将db与app进行关联
5、创建模型:
创建modles.py,这个文件中的每一个类就是定义一张表
模型就是类
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(15), nullable=False)
password = db.Column(db.String(12), nullable=False)
phone = db.Column(db.String(11), unique=True)
redatatime = db.Column(db.DateTime, default=datetime.now)
6、使用命令
*******************************
在app.py中导入模型:from apps.users.modles import Easyops
在终端使用命令:db
python app.py db init # 执行命令后会在项目文件夹中产生一个migrations文件夹,一个项目只需要init一次
再执行命令:db
python app.py db migrate # 会在migrations文件夹下的versions文件夹下生成一个xxxx.py的文件,只要对模型做了任何操作都需要进行migrate
再次执行命令:db
python app.py db upgrade # 就会在mysql对应的数据库中创建表
7、数据的插入
数据的插入可以通过flask的request获取到参数,通过之前创建的连接数据库的类(modeule中的Easyops类)创建连接对象
而后通过db(ext下的__init__中定义)的session.add和session.commit将数据插入到数据库
#####################################
加密方式:md5、sha1、sha256、sha512
import hashlib
在hashlib中有很多的加密方式
######################################
1、查询
# 模型类为module.py文件中对应的类名,每个类就是一张表
查询所有: 模型类.query.all() # 相当于select * from 表名
有条件的查询:
模型类.query.fillter_by(字段名=值) # 相当于select * from 表名 where xxx=xxx 返回值为一个列表
模型类.query.fillter_by(字段名=值).first() # 这是获取条件查询的到第一条记录,相当于 select * from 表名 where xxx=xxx limit 1
select * from table_name where xxx1 > xx and xxx2=xxxx
select * from table_name where xxx1 like 'xxx%'
模型类.query.filter() 里面是布尔类型 模型类.query.filter(模型名.字段名==值)
模型类.query.filter_by() 里面是一个等值 模型类.query.filter_by(字段名=值)
************* 模型类.query.filter() ****************
1、模型类.query.filter().all() 返回一个列表
2、模型类.query.filter().first() 返回一个对象,默认返回第一个对象
#####
字符串的匹配:
lu_info = User.query.filter(User.username.startswith('lu')).all() # 这里是是以username字段中以lu开头的用户,startswith表示以xx开头
lu_info_end = User.query.filter(User.username.endswith('lu')).all() # 这里是以lu结尾的用户
lu_info_cen = User.query.filter(User.username.contains('lu')).all() # 包含,这里是以usernmae中包含lu的用户
user_list = User.query.filter(User.phone.in_(['110', '120'])).all() # 这是user表中phone字段的值在列表中的
user_list = User.query.filter(User.phone == "xxxx").all() # 这是等于的
整形或者日期的匹配:
__lt__(小于)、__gt__(大于)、__ge__(大于等于)、__le__(小于等于) between(x1,x2) (这是范围检索)
也可以:<、 >、 >=、 <=、
使用方法与上面一致,如:
user_list = User.query.filter(User.phone < "xxxx").all()
user_list = User.query.filter(User.phone.__lt__('xxxx')).all() # 这两个都是表示phone字段小于xxx的
user_age = User.query.filter(User.age.between('x1', 'x2')).all() # 这是查询age字段的值在x1到x2之间的
多条件查询:
and_ or_ not_
from operator import or_, and_, not_
select_info = User.query.filter(or_(User.username.like('l%'), User.username.contains('u'))).all() # 这里是查询或者,为包含u或者名字以l开头
表示:sql中的or查询
and_info = User.query.filter(and_(User.username.contains('l'), User.redatatime < '2021-03-07 20:35')).all() # 这里是查询表示and
表示:sql中的and查询,中间的符号也可以用 __lt__(小于)、__gt__(大于)、__ge__(大于等于)、__le__(小于等于)
使用:User.redatatime.__lt__('2021-03-07 20:35') 这里是表示User中redatatime字段的值小于('2021-03-07 20:35')
排序:
order_by()
1、可以直接是字符串:'字段名',但是不能降序,如:order_by('字段名')
2、通过字段名: 模型.字段名 如:order_by(模型.字段名)默认升序 order_by(-模型.字段名) 降序
users_all = User.query.filter(User.username.contains('f')).order_by('redatatime').all() # 这里表示先查询,然后将查询出来的数据通过redatatime字段进行排序,默认惊醒升序排序
user_id = User.query.order_by(User.redatatime).all() # 这里是通过User的redatatime对所有的进行排序,默认进行升序
users_id = User.query.order_by(-User.redatatime).all() # 进行降序,在前面加-
# limit,获取指定数量的记录,一般和offset一起使用
limit_info = User.query.order_by(User.id).limit(2).all() # 这里是将查询出来的值,limit(2获取前两条记录
limit_info1 = User.query.offset(2).limit(2).all() # offset(2)表示跳过前两条,limit(2)再获取两条记录
总结:
1、模型类.query.all() # 查询所有
2、模型类.query.get() # 查询一个
3、模型类.query.filter() # 条件
4、模型类.query.filter_by() # 条件
删除数据:
1、逻辑删除:在定义数据库表时,添加一个字段isdelete,通过次字段控制是否删除,判断这个字段的值
# 从请求中获取到传参id的值
id = request.args.get('id')
# 通过id找到对应的用户,因为id是主键,所以get
id_user = User.query.get(id)
# # 进行逻辑删除
##############################
# 逻辑删除
# id_user.isdelete = True
# db.session.commit()
2、物理删除:从数据库中彻底删除
# 从请求中获取到传参id的值
id = request.args.get('id')
# 通过id找到对应的用户,因为id是主键,所以get
id_user = User.query.get(id)
######################################
# 物理删除
db.session.delete(id_user) # 将对象放到缓存中
db.session.commit() # 提交删除
更新数据:
id = request.form.get('id') # 获取到request请求中带的数据,这是从post请求中 ,get请求使用request.ages.get()
# 通过主键id找到对应的用户
user_info = User.query.get(id) # 获取到对应的用户信息
# 修改用户信息
user_info.phone = phone # 修改phone的值
user_info.username = username # 修改username的值
db.session.commit() # 提交更改,更新对象时不需要add,可直接commit