flask web 基础(二) 通过orm(sql_alchemy)操作数据库

前言

  一个优秀的web框架一定是有一个较为成熟的orm机制的,比如python的django框架的djangoorm, java的Mybatis等都能实现较为全面的orm机制。flask虽然作为一个轻量级的web框架,当然也考虑到了这一点。但是flask并没有自己开发属于自己的orm生态,而是把sqlAlchemy 重新封装为了flask_sqlalchemy插件。

什么是ORM

  ORM的全称为Object Relational Mapping,也简称O/RM,或O/R mapping是一种对象关系映射的计算机技术。是用于实现面向对象编程语言里不同类型系统的数据之间的转换 。简单的来说就是,数据库的记录就是一个对象,而数据库里的每一个字段对应的则是对象的属性。

flask 实现orm

安装准备

  1. flask
  2. mysql
  3. flask_sqlalchemy + pymysql

定义数据库模型

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Author(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False,)
    ages = Column(Integer)
    address = Column(String(50))

如上所示,这里创建了一张Author表

连接数据服务器

映射到数据库有两步,第一步是绑定数据库路径,具体方法是在配置文件中配置,跟配置sqlalchemy的规则大体相同

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:root@localhost/flask_orm'

这里我选择的mysql数据库,当然也可以选择其他的数据库,具体可以参考文档flask-sqlchemy

创建数据库和表
方法一
import click
@app.cli.command()
def initdb():
    db.create_all()
    click.echo("数据表创建成功")

然后在命令行中输入 flask initdb即可,这种方法类似于脚步方法

方法二

在flask的核心对象初始化的时候,执行以下代码片段即可。

db.init_app(app)
with app.app_context():
    db.create_all()

这样在flask定义的数据模型类就在数据库映射成对应的数据表
在这里插入图片描述
表的名字就是类名的小写,表的字段名则对应的是类的属性名,也可以进行修改。

class Author(db.Model):
    __tablename__  =  'athors'

这样就是把命名对应的数据表为authors
简单的来说就是模型类(Author) --> 数据表(author)
模型类属性(name) --> 表字段(name)
表记录 -->类实例

crud操作

新增数据
author1 = Author(name="鲁迅", ages="55", address="北京")
author2 = Author(name="余华", ages="60", address="上海")
author3 = Author(name="菲茨杰拉德", ages="44", address="长岛")
db.session.add(author1)
db.session.add(author2)
db.session.add(author3)
db.session.commit()

在这里插入图片描述
这样数据就同步到了数据库中。

查询数据

这里我们在插入几条数据作为参考

author1 = Author(name="史铁生", ages="59", address="北京")
author2 = Author(name="老舍", ages="67", address="北京")
db.session.add_all([author1,author2])
db.session.commit()

这时候数据库一共有五条记录。
在这里插入图片描述

author = Author.query.all()
    print(author)

[<Author 1>, <Author 2>, <Author 3>, <Author 4>, <Author 5>]
这种查询方式就是查询表Author中的所有记录
就相当于sql 语句 select * from author;
打印列表中每一个类实例就是一条数据库记录
为了方便观察,我把相关结果放到了http页面中,

authors = Author.query.all()
    return render_template('read.html', authors=authors)

具体html代码如下

<table  width="400" border="0" cellspacing="0" cellpadding="0">
    <tr>
        <td>姓名</td>
        <td>年龄</td>
        <td>地址</td>
    </tr>
    {% for author in authors %}
      <tr>
          <td>{{ author.name }}</td>
          <td>{{  author.ages   }}</td>
          <td>{{  author.address }}</td>
      </tr>
    {% endfor %}
</table>

显示结果如下

在这里插入图片描述
当然我们也可以查询第一条数据

  authors = Author.query.first()
  print("姓名", authors.name)
  print("年龄", authors.ages)
  print("地址", authors.address)

在这里插入图片描述
当然我们也可以通过条件进行查找

 authors = Author.query.filter_by(address="北京").all()
    for author in authors:
        print("姓名", author.name,end="")
        print("年龄", author.ages,end="")
        print("地址", author.address)

在这里插入图片描述
也可以多条件查询

authors = Author.query.filter_by(address="北京",ages=55).all()

这时候则只会有鲁迅一条记录了

当然还有更多复杂的查询功能,具体可以参考文档。

删除数据
author = Author.query.filter_by(address="北京",ages=55).first()
db.session.delete(author)
db.session.commit()
authors = Author.query.filter_by(address="北京").all()
for author in authors:
    print("姓名", author.name,end="")
    print("年龄", author.ages,end="")
    print("地址", author.address)

这时候鲁迅这条记录就删除了

修改数据
  author = Author.query.filter_by(address="北京",ages=67).first()
    author.name = "舒庆春"
    db.session.commit()
    authors = Author.query.filter_by(address="北京").all()
    for author in authors:
        print("姓名", author.name,end="")
        print("年龄", author.ages,end="")
        print("地址", author.address)

在这里插入图片描述

数据表之间建立关系

一对多的关系

这种关系在软件设计中并不少见,建立关系的第一步是建立外键,外键(foreign key)用来在A表中存储B表的主键值以便和B表建立联系的关键字段,所以外键总是在多的这一侧来定义。
比如上面我们已经建立了"作者"表,每个作者都发表的多多少少有一些文章,这时候作者和文章就是一对多的关系。

class Book(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50))
    category = Column(String(10))
    author_id = Column(Integer,ForeignKey('author.id'))

author_id则为建立的关键字段
同时在Author表中需要建立关系属性字段,属性名一般和对应的“多”的那一侧的表名相似,当然也看自己的命名喜好。

class Author(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False,)
    ages = Column(Integer)
    address = Column(String(50))
    books = db.relationship('Book')

这个时候我们就可以在Book表新建一些数据

  author = Author.query.filter_by(name="余华").first()
    author_id = author.id
    book1 = Book(title="活着", author_id=author_id)
    book2 = Book(title="许三观卖血记", author_id=author_id)
    book3 = Book(title="射雕英雄传", author_id=author_id)
    db.session.add(book1)
    db.session.add(book2)
    db.session.add(book3)
    db.session.commit()
        for name in author.books:
        print(name.title)

在这里插入图片描述
想要解除一对多的关系也较为简单

author = Author.query.filter_by(name="余华").first()

book = Book.query.filter_by(title="射雕英雄传").first()
author.books.remove(book)
db.session.commit()
for name in author.books:
    print(name.title)

在这里插入图片描述
当然也可以建立双向关系

class Author(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False,)
    ages = Column(Integer)
    address = Column(String(50))
    books = db.relationship('Book',back_populates='author')

class Book(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50))
    category = Column(String(10))
    author_id = Column(Integer,ForeignKey('author.id'))
    author = db.relationship('Author', back_populates='books')
author = Author.query.filter_by(name="余华").first()

for name in author.books:
    print(name.title)
book = Book.query.filter_by(title="活着").first()
print("作者名称",book.author.name)

在这里插入图片描述

一对一关系

一对一关系其实是一对多关系的一些改动

class Author(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False,)
    ages = Column(Integer)
    address = Column(String(50))
    books = db.relationship('Book',back_populates='author')
    wife = db.relationship('Wife',uselist=False)


class Wife(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False, )
    author_id = Column(Integer, ForeignKey('author.id'))
    author = db.relationship('Author')

这里的wife表跟作者表为一对一的关系,这里面部考虑离婚再娶的关系。

author = Author.query.filter_by(name="余华").first()
wife = Wife(name="陈虹",author_id=author.id)
db.session.add(wife)
db.session.commit()
print("作者{}的妻子是{}".format(author.name,author.wife.name))

在这里插入图片描述

多对多的关系

多对多的关系其实是再新建一个关系表,来满足其的关系
这里暂且不提,再后面的数据表级联关系文章中再详细介绍

美中不足

任何一个框架都有他的优缺点,flask_sqlalchemy更是如此,一方面他表现了他的轻,包括sqlchemery本身带的线程池的优势。而另一方面他作为一个web的orm框架稍显不足,比如当
需要对数据表进行更新时是没有办法的,只能通过
db.drop_all()
db.create_all()
的方法其实就是把表删了,然后建立新的表。
这点就远不如django框架的灵活与强大的,包括各个关系的声明django框架也简单的多,轻就代表自由,代表多变,但是也代表需要我们做的事情更多,这也是python 的两代框架django和flask可以并驾齐驱的原因吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值