40
社区成员




不知道诸位什么时候才打开这篇教程,前面的东西还记得几多?
不过没事.jpg
所有的学习都是要保留一个最基础的思想,哪怕你把Flask忘得一干二净,只要你还记得前后端是个什么玩意儿完成什么工作。
其他的有AI呢(bushi)
到此还不够,前端后端分不开,后端和数据库更是分不开。
关于这句话,在了解前后端和数据库基本的构造之后就可以讲了。
还是举例子来说,现在用户要登录了,它在前端的界面中输好了账号密码,通过POST请求发送到服务器了,然后……呢?
服务器怎么对有没有这个用户,密码有没有输入正确进行判断?
将某些凭证及用户数据存下来,在需要的时候通过各种字段进行筛选,得到想要的数据,比对或者返回。
至于图片或者视频这些东西……数据库一般而言是无能为力的。
但是Flask可以调取服务器内部的文件(比如图片和视频)返回给前端,数据库就可以用来存路径或者文件名。
感兴趣可以自己去学哈。
我们再说说配环境的事。
……
不细讲了啊,多装一个flask_sqlalchemy库就OK了,pip install还是Setting里面装都OK。
SQLALchemy 实际上是对数据库的抽象,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升
SQLAlchemy是一个关系型数据库框架,它提供了高层的 ORM 和底层的原生数据库的操作。flask-sqlalchemy 是一个简化了 SQLAlchemy 操作的flask扩展
大概看懂就OK。
装好了我们就来讲操作了。
请打开你的MySQL数据库的Workbench,根据前面的教的东西创建好一个空的数据库,然后我们就来给Flask配置数据库。
# 配置一个数据库
HOSTNAME = "127.0.0.1" # 数据库位置
PORT = 3306 # 数据库管理端口,在workbench最初始的页面,别忘了
USERNAME = "root" # 管理员名字
PASSWORD = "Abc123456"
DATABASE = "database_test" # 数据库名字
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
#app.config里面设置好连接数据库的信息
#SQLALchemy会自动读取app.config内连接数据库的信息
#使用SQLALchemy创建一个db对象
db = SQLAlchemy(app)
最开始的五行配置应该很好理解吧。
最长的那一行可以不理解,照抄就好。本质是利用上面设定好的五个变量再通过Flask自带的配置能力链接上数据库。
先上代码,我再讲。
class User(db.Model): #映射进入数据库内部
__tablename__ = "user_1" #表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) #设置字段,且为主键,自主增长
#string在数据库中为varchar
username = db.Column(db.String(100), nullable=False) #设置用户名字段,为字符串类型,可设置长度,设置不可为空
password = db.Column(db.String(100), nullable=False) #设置密码字段,参数同上
db = SQLAlchemy(app)
: Flask 应用的初始化,其中 app
是 Flask 应用实例。SQLAlchemy(app)
创建了一个 SQLAlchemy 实例,用于管理数据库操作。
class,即类。是python内部的一个东西。这一段代码表示,这个类在目前的python程序内部被命名为User,括号内部的东西表示User继承自 db.Model
db.Model
是 SQLAlchemy 提供的基类,用于定义数据库模型(即数据库表的结构)。
__tablename__
代表的是这个User类在数据库中映射的数据表的名字
一整句就是说Python里的User类,它的映射是数据库中的一个叫做user_1的模型。
(说白了就是数据库中的其中一张表,表的名字叫做user_1。)
随后就是设置字段,翻译一下就是id
是 User
类(即数据库表 user_1
)中的一个字段(列)。
剩下的应该很好懂,我只做一些简单的补充。
db.ForeignKey('')
以及db.relationship('', backref=‘’, lazy=True)
。这个被称作外键约束,举个例子比较好理解,假设你是SZU的学生,SZU的学生奖项,那你就可以这样写代码。class SZU_prize(db.Model):
__tablename__ = "szu_prize"
prize_id = db.Column(db.Integer, primary_key=True)
stu_id = db.Column(db.Integer, db.ForeignKey('szu_stu.id'))
# 括号里面的字符串格式为 数据表名.列名
# 注意是数据表的名字,不是类的名字
class SZU_stu(db.Model):
__tablename__ = "szu_stu"
id = db.Column(db.Integer, primary_key=True)
prizes = db.relationship('SZU_prize', backref='student', lazy=True)
# 括号里面的意义为 类名,新属性的名字,延迟加载(节省内存的一种方法,只在用到它的时候才加载
# 这里 prizes 是新属性的名字,代表与该学生相关联的所有奖项
# backref='student' 在 SZU_prize 模型中创建了一个名为 student 的反向引用属性
# 也就是说我在两个表里都开了一个新属性
简单的用逻辑关系描述一下,你是拿过奖的SZU的学生,你的学生id就一定在SZU的奖项数据库里,而且你一个人可以对应着多个奖项。
这就是一对多的关系,还有多对一,多对多的关系。这个涉及到的是数据库的结构设计,比如使得查询更简洁更方便更快,减少冗余数据,保证数据的一致性等等,这的确是一门值得钻研的学问。感兴趣就可以自己去查资料学习了,小项目的开发中不会用到很复杂的数据库。
这个本身跟查询结合的很紧密,我就先写了,后面会具体教查询,到时候再倒回来看吧。
# 假设有一个奖项的id为10086
prize = SZU_prize.query.get(10086) # 在SZU_prize表中找到id为10086的对象(那一行
print(prize.stu_id, prize.student.id) # 那一行里既有stu_id,也有student
# 二者返回一样的值,因为 backref 创建了反向引用
前者在于保证数据的可靠性,确立表之间的从属关系。因为外键约束的存在,必须要先在szu_stu表中存在你的id数据,szu_prize表中的stu_id才能有你的数据,就是说不能莫名其妙冒出一个不是SZU的学生,但是SZU获得的奖项学生id却有他。
后者是提供一个更快速的检索方式,比如我想了解你的获奖情况,我就可以利用这个反向引用从stu表快速连接到奖项表了解到你一个人的获奖情况,比拿id去查询会快,而且更易于维护,尤其是在数据表很多字段很多的情况下,可以简化查询的条件。
这里权作数据库进一步深入的引入,感兴趣的就可以自己去找资料了。
在教操作之前,我们先要知道两个调试必备的代码。
with app.app_context(): # 这句是建立上下文关系,原理可以自己找,可以不写,但有概率报错
# db.drop_all() #删除所有数据库
db.create_all() #建立数据库,这个一定要写。
毕竟要是很麻烦,全删了重建一次就好。
直接全丢出来,接好了。
class User(db.Model): #映射进入数据库内部
__tablename__ = "user_1" #表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True) #设置字段,且为主键,自主增长
#string在数据库中为varchar
username = db.Column(db.String(100), nullable=False) #设置用户名字段,为字符串类型,可设置长度,设置不可为空
password = db.Column(db.String(100), nullable=False) #设置密码字段,参数同上
@app.route('/user/add') #增添数据
def user_add():
# 创建ORM对象,设计一条数据,包含数据库内的字段
user1 = User(username="admin", password="123")
user2 = User(username="admin", password="12345")
user3 = User(username="张三", password="abc")
#使用add_all(),方法一次性添加多个对象 但首先需要将它们放入一个列表中
# 如果只有一个,那就db.session.add(user1)
users_to_add = [user1, user2, user3]
db.session.add_all(users_to_add) #将ORM对象添加到db.session中
#将db.session中的改变同步到数据库中,每一步对数据库进行操作都要有这个。
db.session.commit()
return "用户创建成功"
@app.route('/user/query') #查找数据
def query():
# 1.get查找,根据主键查找
#user = User.query.get(1) 查找到主键值为1的User对象(就是一行的数据
#print(f"{user.id}:{user.username}:{user.password}")
#return "数据查找成功"
# 2.filter.by查找
users = User.query.filter_by(username="admin")
#通过用户名来查找,查找所有为admin的用户,但不支持模糊搜索
for user in users:
print(user.username,user.password) # 可以调用user内的全部字段
return "数据查找成功"
# User.query.all() 获取表中的全部的User数据,返回数据为列表类型
# .exists() 判断数据是否存在
@app.route('/user/update')
def update():
#查找得到其中的数据
user = User.query.filter_by(username="张三").first()
# 不加first返回的是一个对象而不是一个实例
# 但所有删改都智能对某一个特定实例进行,所以必须要将实例从对象中取出
user.password = "aaaaa" # 更改user的数据
db.session.commit() #同步到数据库
return "数据修改成功!"
@app.route('/user/delete')
def delete():
# 查找到对应的数据
user = User.query.filter_by(username="张三").first()
# db.session中删除对应数据
db.session.delete(user)
# 同步到数据库
db.session.commit()
return "数据删除成功!"
没啥好讲的,都是固定格式的东西,基础的增删改查都在这里。只有查询这一点东西比较多,像是模糊搜索,多条件查询,筛选空或者非空的值,排序并筛选前十名等等。操作很多,我不多提,因为一问AI都有,与其花时间背代码,不如多看点开源项目。记住一点就好,项目开发不是闭卷考试。
好了,学到这里,你们已经具备了在小项目中进行后端开发的基本能力了。到目前为止,你应该了解前后端跑通的一整个逻辑是什么,并且能够处理前端传来的各式各样的请求,并且根据请求到数据库中增添,查询,删改某些数据,并将相关的数据返回给前端。
那前端呢?
关于前端,我们后续会学习HarmonyOS NEXT的开发,将你们培养成能够一人担起整个前后端开发的项目能手。