lhl
首页
python
leetcode
产品思想
软件测试
博客 (opens new window)
github (opens new window)
首页
python
leetcode
产品思想
软件测试
博客 (opens new window)
github (opens new window)
  • python

    • Python 基础

    • Python 数据库

    • 面向对象

    • Python Web

      • flask 入门
      • flask 与 http
      • flask模板
      • flask表单
      • flask数据库
        • ORM
        • 定义关系
    • Python 进阶

  • leetcode

  • 软件测试

  • Git

  • linux

  • 产品

  • MySql

  • docker

  • python
  • Python_Web
2024-05-06
目录

flask数据库

# ORM

Web 应用 中使用 原生 sql 的问题:

  1. 手动编写 SQL 语句低效,而且视图函数中加入太多 SQL 语句会降低代码的易读性。另外还会容易出现安全问题,比如SQL注入。
  2. 常见的开发模式是在开发时使用简单的SQLite,而在部署时切换到MySQL等更健壮的DBMS。但是对于不同的DBMS,我们需要使用不同的Python接口库,这让DBMS的切换变得不太容易。
  3. 注意 尽管使用ORM可以避免SQL注入问题,但你仍然需要对传入的查询参数进行验证。另外,在执行原生SQL语句时也要注意避免使用字符串拼接或字符串格式化的方式传入参数。

ORM 可以避免大部分问题。

ORM 把底层的 SQL 数据实体转化成高层的Python对象。

ORM 主要实现了三层映射关系:

  • 表→Python类。
  • 字段(列)→类属性。
  • 记录(行)→类实例。

ORM 优点:

  1. 便于使用
  2. 灵活性好
  3. 提升开发效率, 原生 SQL 的性能效率是比 ORM 高,但是损失一点性能效率来提升开发效率
  4. 可移植性高,ORM 支持多种 DBMS, 包括MySQL, Oracle等

# 使用 ORM

# sql
# CREATE TABLE contacts(
#     name varchar(100) NOT NULL,
#     phone_number varchar(32),
# );

# ORM
from foo_orm import Model, Column, String

class Contact(Model):
    __tablename__ = 'contacts'
    name = Column(String(100), nullable=False)
    phone_number = Column(String(32))

# 插入 contacts
# INSERT INTO contacts(name, phone_number) 
# VALUES('Grey Li', '12345678');


# 等价于
# ORM
contact = Contact(name='Grey Li', phone_number='12345678')

# 连接数据库服务器

# URI

sqlite:////tmp/test.db, sqlite

mysql://username:password@server/db, mysql

# 字段类型

字段 说明
Integer 整数
String(n) 字符串, n 设置最大长度
Text Unicode文本
Date 日期, Python datetime.date
Time 时间, Python datetime.time
DateTime 时间和日期, Python datetime.timedelta
Float 浮点数
Boolean 布尔数
PickleType Pickle 列化的 Python 对象
LargeBinary 任意二进制数据

# 字段参数

字段 说明
primary_key 如果设为 True, 该字段为主键
unique 如果设为 True, 该字段不允许出现重复值
index 如果设为 True, 为该字段创建索引,提高查询效率
nullable 确定字段值可否为空,值为 True 或 False, 默认值是 True
default 为字段设置默认值

# 表名

默认是 模型类的名称, 如果想指定表名称, 通过 __tablename__ 属性指定

# 数据库操作

# create, 增

>>> from app import db, Note
>>> note1 = Note(body='remember Sammy Jankis')
>>> note2 = Note(body='SHAVE')
>>> note3 = Note(body='DON\'T BELIEVE HIS LIES, HE IS THE ONE, KILL HIM')
>>> db.session.add(note1)
>>> db.session.add(note2)
>>> db.session.add(note3)
>>> db.session.commit()
  1. db.session.add(), 添加一条记录
  2. db.session.add_all(), 一次性添加多条记录
  3. db.session.commit(), 提交会话

# Read, 查

查询语法,<模型类>.query.<过滤方法>.<查询方法>。

常用的SQLAlchemy查询方法

常用查询方法 说明
all() 返回包含所有查询记录的列表
first() 返回查询的第一条记录,如果未找到,则返回 None
one() 返回第一条记录,且仅运行只有一条。如果查询结果数量大于小于1,则抛出错误
get(id) 传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回 None
count() 返回查询结果的数量
with_parent(instance) 出入模型类实例作为参数,返回和这个实例相关联的对象
paginate() 返回一个 Pagination 对象, 可以对记录进行分页处理
常用过滤方法 说明
filter() 使用指定的规则过滤记录
filter_by() 返回指定规则过滤记录(关键字)
order_by() 根据指定条件对记录进行排序
limit(limit) 使用指定的值限制原查询返回的记录数量
group_by() 根据指定条件对记录进行分组
offset(offset) 使用指定的值偏移原查询的结果

# update, 改

>>> note = Note.query.get(2)
>>> note.body
u'SHAVE'
>>> note.body = 'SHAVE LEFT THIGH'
>>> db.session.commit()

# delete, 删除

>>> note = Note.query.get(2)
>>> db.session.delete(note)
>>> db.session.commit()

# 定义关系

# 一对多

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), unique=True)
    phone = db.Column(db.String(20))
    # 关系

    articles = db.relationship('Article')  # collection

    def __repr__(self):
        return '<Author %r>' % self.name


class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), index=True)
    body = db.Column(db.Text)
    # 外键
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))

articles = db.relationship('Article'),这个属性并没有使用Column类声明为列,而是使用了db.relationship()关系函数定义为关系属性,因为这个关系属性返回多个记录,我们称之为集合关系属性。

relationship() 函数的第一个参数为关系另一侧的模型名称,它会告诉 SQLAlchemy 将 Author 类与 Article 类建立关系。

当这个关系属性被调用时,SQLAlchemy 会找到关系另一侧(即article表)的外键字段(即author_id),

然后反向查询article表中所有author_id值为当前表主键值(即author.id)的记录,返回包含这些记录的列表,

也就是返回某个作者对应的多篇文章记录。

author_id = db.Column(db.Integer, db.ForeignKey('author.id')), 外键定义

# 多对多

# 交给 orm 管理
association_table = db.Table('association',db.Column('student_id', db.Integer, db.ForeignKey('student.id')),db.Column('teacher_id', db.Integer, db.ForeignKey('teacher.id')))

class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(70), unique=True)
    grade = db.Column(db.String(20))
    teachers = db.relationship('Teacher',
        secondary=association_table,
        back_populates='students')

class Teacher(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(70), unique=True)
    office = db.Column(db.String(20))

关联表使用db.Table类定义,传入的第一个参数是关联表的名称。

我们在关联表中定义了两个外键字段:teacher_id字段存储Teacher类的主键,student_id存储Student类的主键。

#flask#数据库
flask表单
协程

← flask表单 协程→

最近更新
01
lhl learn notes
02
filter
06-09
03
decorator
06-09
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式