FLASK核心操作之ORM

ORM

一、概要

1、说明

ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法,

2、核心模块SQLAlchemy ORM 和SQLAlchemy Core

  1. Core是一种构建在表达式语言之上的一种API,一种SQL抽象工具包,允许用户以Python的语法格式构建SQL表达式,
  2. ORM 基于Core之上,一种更高级的、更加抽象的一种使用模式,其提供了现实业务对象与关系型数据库中表的一种关联关系,并实现两者之间的轻松转换

3、ORM优缺点

  1. 优点

    1、隐藏了数据访问细节,封闭的通用数据库交互,ORM的核心,它使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。

    2、ORM使我们构造固化数据结构变得简单易行。

  2. 缺点

    1、无可避免,自动化意味着映射和关联管理,代价是牺牲性能

##二、前期准备工作

1、安装插件

  1. 安装flask-sqlalchemy

    pip install flask-sqlalchemy
    
  2. 安装Flask-Migrate

    pip3 install Flask-Migrate
    

2、数据库设置

  1. 配置连接地址

    #mysql 
    mysql+pymysql://user:password@ip:port/db_name
    #oracle 
    oracle+cx_oracle://user:password@ip:port/db_name
    
  2. 实例化SQLAlchemy

    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    
  3. 注册

    # 需要Flask对象
    db.init_app(app)
    
  4. 设置加载的url

    app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root:root@127.0.0.1:3306/flask'
    
  5. 配置migrate

    # 实例化Migrate
    migrate = Migrate()
    migrate.init_app(app=app, db=db)
    
    # 添加命令脚本
    from flask_migrate import MigrateCommand
    manager.add_command('db', MigrateCommand)
    

三、使用

1、定义模型

  1. 说明

    模型表示程序中使用的持久化实体,在ORM中,模型是一个类,类中的属性对应数据库表中的,类名对应数据库中的表名

    持久化:是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)

  2. 新建models.py文件

    class User(db.Model):
        uid = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), index=True, unique=True, nullable=False)
        email = db.Column(db.String(100), index=True, unique=True)
        phone = db.Column(db.String(length=11), index=True, unique=True)
        age = db.Column(db.Integer, index=True, unique=True)
    

2、列类型对应的Python类型

  1. 类型

    类型名Python类型说 明
    Integerint普通整数,一般是32位(常用)
    SmallIntegerint取值范围小的整数,一般是16位
    BigIntegerint或long不限制精度的整数
    Floatfloat浮点数
    Numericdecimal.Decimal定点数
    Stringstr变长字符串(常用)
    Textstr变长字符串,对较长或不限长度的字符串做了优化(常用)
    Unicodeunicode变长Unicode字符串
    UnicodeTextUnicode变长Unicode字符串,对较长或不限长度的字符串做了优化
    Booleanbool布尔值
    Datedatetime.date日期
    Timedatetime.time时间
    DateTimedatetime.datetime日期和时间(常用)
    Intervaldatetime.timedelta时间间隔
    Enumstr一组字符串
    PickleType任何Python对象自动使用pickle序列化
    LargeBinarystr二进制文件
  2. 选项

    选项名说明
    primary_key如果设为True,这列就是表的主键
    unique如果设为True,这列不允许出现重复的值
    index如果设为True,为这列创建索引,提升查询效率
    nullable如果设为True,这列允许使用空值,如果设为False,这列不允许使用空值
    default为这列设定默认值
  3. 定义关系类型常用

    选项名说明
    backref在关系的另一个模型中添加反向引用
    primaryjoin明确指定两个模型之间使用的联结条件,只在模棱两可的关系中需要指定
    lazy指定如何加载相关记录,可选值有select(首次访问时按需加载)、immediate(源对象加载后就加载)、joined(加载记录,但使用联结)、subquery(立即加载,但使用子查询)、noload(永不加载)和dynamic(不加载记录,但提供加载记录的查询)
    uselist如果设为False,不使用列表,而使用标量值
    order_by指定关系中记录的排序方式
    secondary指定多对多关系中关系表的名字
    secondaryjoinSQLAlchemy无法自行决定时,指定多对多关系中的二级联结条件

3、添加数据

  1. 添加单个对象

    @user.route('/add/', methods=['post', 'get'])
    def add():
        if request.method == 'GET':
            return render_template('user/add.html')
        else:
            username = request.form.get('username')
            email = request.form.get('email')
            phone = request.form.get('phone')
            user = User(username=username, email=email, phone=phone)
            db.session.add(user)
            db.session.commit()
            users = User.query.all()
            return render_template('user/users.html', users=users)
    
  2. 添加多个对象

    @user.route('/add/', methods=['post', 'get'])
    def add():
        if request.method == 'GET':
            return render_template('user/add.html')
        else:
            db.session.add_all([User(username='test1', email='123@163.com', phone=12345678936),
                                User(username='test2', email='1234@163.com', phone=123456789326)])
            #提交
            db.session.commit()
            return '添加多个对象'
    

4、更新数据

  1. 更新单个对象

    @user.route('/update/<int:uid>/<username>/')
    def update(uid,username):
        user = User.query.filter_by(username=username).first()
        if user:
            user.email = '12345@example.com'
        	db.session.commit()
    	# 或者
        user = User.query.get(uid)
        if user:
           user.username = '小明'
           db.session.commit()
    	#或者
        user = User.query.filter_by(uid=uid).update({"username": "hehe"})
        db.session.commit()
        return '更新单个对象'
    
  2. 批量更新

    # synchronize_session设置为False即执行字符串拼接
    User.query.filter(User.like('_e%')).update({User.name: User.name + "test"}, synchronize_session=False)
    
    # synchronize_session设置为evaluate即执行四则运算
    User.query.filter(User.id > 0).update({"age": User.age + 1}, synchronize_session="evaluate")
     
    

5、删除数据

  1. 操作步骤

    @user.route('/del/<int:uid>/')
    def delete(uid):
        user = User.query.get(uid)
        if user:
            db.session.delete(user)
            db.session.commit()
        return redirect('user/show/')
    

6、查询数据

  1. 查询过滤器

    过滤器说明
    filter()条件过滤,把过滤器添加到原查询,返回新查询
    filter_by()把等值过滤器添加到原查询,返回新查询
    limit()使用指定值限制原查询返回的结果数量,返回新查询
    offset()偏移原查询返回的结果,返回新查询
    order_by()排序返回结果,返回新查询
    groupby()原查询分组,返回新查询

    说明

这些过滤器返回的结果都是一个新查询,我的理解是这些查询其实是生成的SQL语句,lazy的惰性求值方式也体现在查询上,而这些语句不能生成需要查询的对象,需要调用其他的方法生成对象。

  1. SQL查询执行函数

    方法说明
    all()以列表形式返回结果
    first()返回第一个结果,如果没有返回None
    first_or_404()返回第一个结果,如果没有抛出404异常
    get()返回主键对应记录,没有则返回None
    get_or_404()返回主键对应记录,如果没有抛出404异常
    count()返回查询结果数量
    paginate()返回paginate对象,此对象用于分页
  2. 操作符号

    • equals

      query.filter(User.name == '小明')
      
    • not equals:

    query.filter(User.name != '小明')
    
    • LIKE:

      query.filter(User.name.like('%小%'))
      
    • IN

      query.filter(User.name.in_(['小明', '小红', '小花']))
      
      query.filter(User.name.in_(
              db.session.query(User.name).filter(User.name.like('%小%'))
      ))
      
    • NOT IN:

      query.filter(~User.name.in_(['小明', '小红', '小花']))
      
    • IS NULL:

      query.filter(User.name == None)
      query.filter(User.name.is_(None))
      
    • IS NOT NULL

    query.filter(User.name != None)
    query.filter(User.name.isnot(None))
    
    • AND
    query.filter(and_(User.name == '小明', User.age == 18))
    
    • OR
    query.filter(or_(User.name == '小明', User.name == '小花'))
    
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值