• flask再学习-思考之怎么从数据库中查询数据在页面展示!


    看别人视频觉得很简单,要自己做蒙蔽了!这样子。NO!

    1. 流程:

    首先要有和数据库连接的驱动!一般有PYMySQL mysqlclient 等

    使用扩展Flask-SQLAlchemy 获得orm对象

    重点在于ORM对象的使用:

    官方文档:http://docs.jinkan.org/docs/flask/patterns/sqlalchemy.html

    http://www.pythondoc.com/flask-sqlalchemy/queries.html

    2:使用 flask-sqlacodegen 扩展 方便快速生成 ORM model

         2.1 :pip install flask-sqlacodegen

         2.2 使用方法

           生成所有表的对象:

         flask-sqlacodegen mysql://root:@127.0.0.1/food_db --outfile "common/models/model.py"  --flask

      生成某个表的对象:

        flask-sqlacodegen mysql://root:@127.0.0.1/food_db --tables user --outfile "common/models/user.py"  --flask

      注意:在window下mysql的部分不要加 ‘ ’ ,在Mac环境下要加  ‘ ’

    3: 修改自动生成的model中的db变量

          from application import db

    4:修改配置文件   

         SQLALCHEMY_DATABASE_URI = 'mysql://root:对应root的密码@127.0.0.1/food_db'

    5:开始写代码了

    【前言】

    使用python处理mysql数据库相关的业务,一般都是使用库MySQLdb直接调用sql语句。感觉很low,换一个SQLAlchemy上手。不但是耍酷,之前些flask代码时就很惊讶基本看不到对数据库的操作,其使用的就是修改过的SQLAlchemy,好处是直接操作数据库表对象,即ORM对象关系映射管理,性能会慢些,但在1-2倍的时间,在可以接受的范围。

    安装

    pip install sqlalchemy
    pip install --egg mysql-connector-python-rf
    pip install sqlacodegen

    生成models

    1. 方法一: 自己根据SQLAlchemy的docs写model,比如一对多,多对一等复杂的表模型。(SQLAlchemy的文档非常详细,就跟天书一样,真心懒得看。还是flask-sqlalchemy的文档简洁明了,可以参考的)

    2. 方法二: 使用sqlacodegen从数据库逆向出models.py

    $ sqlacodegen --noviews --noconstraints --noindexes 
    --outfile ./models.py mysql://username:password@localhost:3399/dbname 

    这里需要注意下,使用–noviews, –noconstraints, –noindexes,这3个选项是去掉视图,约束和所以,基本用不到。反之,不去带着些文件结构的话可能会报错,比如views找不到数据。

    数据库表-User

    idnameage
    1 ‘Tom’ 22
    2 ‘Jim’ 21
    3 ‘Lucy’ 22

    对应的models.py

    # 导入:
    from sqlalchemy import Column, String, create_engine
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    
    # 创建对象的基类:
    Base = declarative_base()
    
    # 定义User对象:
    class User(Base):
        # 表的名字:
        __tablename__ = 'user'
    
        # 表的结构:
        id = Column(String(20), primary_key=True)
        name = Column(String(20))

    基本使用

    首先要创建engine,它代表一种数据库连接资源。可以通过engine船舰connect和session完成事务的提交。对于使用os.fork或者multiprocessing的多进程应用来说,通常需要为紫禁城提供单独的engine。

    mysql:

    engine = create_engine('mysql://scott:tiger@localhost/test')
    
    #比较好的习惯是现实销毁引擎,会有助于python的垃圾回收
    engine.dispose()

    sqlite:

    engine = create_engine('sqlite:///file.db')

     

    查询记录

    那么我们怎么从数据库中查询数据?为此,SQLAlchemy 在您的 Model 类上提供了 query 属性。当您访问它时,您会得到一个新的所有记录的查询对象。在使用 all() 或者 first() 发起查询之前可以使用方法 filter() 来过滤记录。如果您想要用主键查询的话,也可以使用 get()。

    connect:

    connection = engine.connect()
    result = connection.execute("select username from users")
    for row in result:
        print("username:", row['username'])
    connection.close()

    Session:

    # 创建DBSession类型:
    DBSession = sessionmaker(bind=engine)
    # 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
    user = session.query(User).filter(User.id=='5').one()
    # 打印类型和对象的name属性:
    print 'type:', type(user)
    print 'name:', user.name
    # 关闭Session:
    session.close()

    使用更复杂的表达式查询一些用户:

    >>> User.query.filter(User.email.endswith('@example.com')).all()
    [<User u'admin'>, <User u'guest'>]

    按某种规则对用户排序:

    >>> User.query.order_by(User.username)
    [<User u'admin'>, <User u'guest'>, <User u'peter'>]

    限制返回用户的数量:

    >>> User.query.limit(1).all()
    [<User u'admin'>]

    用主键查询用户:

    >>> User.query.get(1)
    <User u'admin'>

    打印查询结果的全部元素:

    for u in session.query(User).all():
        print u.__dict__

    插入记录

    插入记录ret = session.add(),其中ret的值永远是none,不用看。

    Session:

    try:
        sess = Session()
        sess.add(User())
        sess.commit()
    except gevent.Timeout:
        sess.invalidate()
        raise
    except:
        sess.rollback()
        raise

    删除记录

    删除记录是十分类似的,使用 delete() 代替 add():

    >>> db.session.delete(me)
    >>> db.session.commit()

    更改记录

    基本思路是先filter到需要的行集合,再修改里面的值。这里有4种方式:

    1) user.no_of_logins += 1
       session.commit()
    
    2) session.query().
           filter(User.username == form.username.data).
           update({"no_of_logins": (User.no_of_logins +1)})
       session.commit()
    
    3) conn = engine.connect()
       stmt = User.update().
           values(User.no_of_logins = (User.no_of_logins + 1)).
           where(User.username == form.username.data)
       conn.execute(stmt)
    
    4) setattr(user, 'no_of_logins', user.no_of_logins+1)
       session.commit()

    事务

    事物就是有一系列动作一气呵成,如果中间失败了,前面的动作不会生效。满足ACID特性。

    最简单的例子就是转账,我给你转10块钱后台需要做两件事,先在我账户中减去10,再在你的账户里加10。想想如果这件事不用事务处理,我卡里减了10块钱,而转你钱没有成功,这十块钱就莫名消失了哈。

    connection = engine.connect()
    trans = connection.begin()
    try:
        r1 = connection.execute(table1.select())
        connection.execute(table1.insert(), col1=7, col2='this is some data')
        trans.commit()
    except:
        #一旦出错就回滚
        trans.rollback()
        raise
    connection.close()

    参考文献

    stackoverflow.com: Convert sqlalchemy row object to python dict

  • 相关阅读:
    springboot2 整合雪花算法,并兼容分布式部署
    docker 在 linux 搭建私有仓库
    jdbc 几种关系型数据库的连接 和 driver_class,以及简单的使用
    springboot2 整合发送邮件的功能
    oracle 唯一新约束 和 逻辑删除的 冲突处理办法
    oracle 一些常见操作方法
    spring-cloud-stream 整合 rabbitmq
    springboot2 整合 rabbitmq
    docker 安装 rabbitmq 消息队列
    网络统计学目录
  • 原文地址:https://www.cnblogs.com/xussi/p/9576595.html
Copyright © 2020-2023  润新知