zoukankan      html  css  js  c++  java
  • Mysql存储之ORM框架SQLAlchemy(一)

    上一篇我们说了mysql存储的原生语句方式,因为原生语句每次写都比较的复杂,所以这里我们说一种引用实体类的方式来操作数据库。

    什么是ORM

    ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上
    也就是说不用再操作mysql的底层语句,而是通过操作映射后的对象。

    安装与导入Sqlalchemy包

    安装需要

    pip install sqlalchemy
    另外这里用了pymysql作为引擎,所以还要运行

    pip install pymysql
    导入需要的包

    from sqlalchemy import (create_engine,MetaData)
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    

    创建一个engine

    链接形式:'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'

    #basic.py
    connect_str= "mysql+pymysql://root:@localhost:3306/test?charset=ut8mb4"
    engine = create_engine(connect_str,echo=True)
    Base=declarative_base()#生成一个SqlORM 基类
    Session=sessionmaker(bind=eng,expire_on_commit=False)#bind绑定,创建与数据库的会话session class
    db_session=Session()
    metadata=MetaData(engine )# 绑定元信息
    __all__ = ['eng', 'Base', 'db_session', 'metadata']#返回提供给后面程序用
    

    create_engine()用来初始化数据库连接
    echo=True对打印出原始的sql语句。默认Flase

    当我们使用ORM的时候,其配置过程主要分为两个部分:一是描述我们要处理的数据库表的信息,二是将我们的Python类映射到这些表上。这两个过程在SQLAlchemy中是一起完成的,我们将这个过程称之为Declarative
    使用Declarative参与ORM映射的类需要被定义成为一个指定基类的子类,这个基类应当含有ORM映射中相关的类和表的信息。这样的基类我们称之为declarative base class。在我们的应用中,我们一般只需要一个这样的基类。这个基类我们可以通过declarative_base来创建,

    创建表结构

    #tables.py
    #-*- coding=utf-8 -*-
    from sqlalchemy import (
        Table, Column, INTEGER, String, Text,DateTime,BIGINT,CHAR,DECIMAL)
    from .basic import metadata
    import datetime
    
    dl_item=Table("test",metadata,
                    Column("id",BIGINT,primary_key=True,autoincrement=True),
                    Column("name",String(30)),
                    Column("hobby",String(45)),
                    Column("date",DateTime),
    )
    

    创建模型映射

    #model.py
    # -*- coding=utf-8 -*-
    from dbs.basic import Base
    from dbs.tables import *
    
    class LoginInfo(Base):
        __table__=test#填写表名
    

    1.从Base派生一个名为LoginInfo的类,在这个类里面我们可以定义将要映射到数据库的表上的属性(主要是表的名字,列的类型和名称等).
    2.类至少应该包含一个名为tablename的属性来给出目标表的名称,以及至少一个Column来给出表的主键(Primary Key)

    查询操作

     list = db_session.query(LoginInfo).filter_by(name="zs",hobby="music")
    .filter(LoginInfo.id.in_([1,2,3,4,5])).order_by(LoginInfo.id).all()
    for item in list:
       print(item.__dict__) #通过循环,然后获取对象的所有属性方法。
    

    filter_by不支持使用mysql中的in 操作,所有使用filter,但是要注意的是使用filter查询的时候,需要对象.属性进行字段的操作。
    下面是关于filter的更多方法:

    等于
    query.filter(LoginInfo.name == 'zs')#等于
    
    不等于
    query.filter(LoginInfo.name != 'zs')#不等于
    
    LIKE
    query.filter(LoginInfo.name.like('%an%'))#like语句
    
    IN
    query.filter(LoginInfo.name.in_(['zs', 'ls', 'ww']))#in语句
    或者类似的使用子查询
    query.filter(User.name.in_(
            session.query(LoginInfo.name).filter(LoginInfo.name.like('%an%'))
    ))
    
    NOT IN
    query.filter(~LoginInfo.name.in_(['zs', 'ls', 'ww']))#not in 
    
    IS NULL
    query.filter(LoginInfo.name == None)#is null
    或
    query.filter(LoginInfo.name.is_(None))
    
    IS NOT NULL
    query.filter(LoginInfo.name != None)#IS NOT NULL:
    或者
    query.filter(LoginInfo.name.isnot(None))
    
    AND
    from sqlalchemy import and_
    query.filter(and_(LoginInfo.name == 'zs', LoginInfo.hobby == 'music'))
    或者
    query.filter(LoginInfo.name == 'zs', LoginInfo.hobby == 'music')
    或者连续使用filter
    query.filter(LoginInfo.name == 'zs').filter(LoginInfo.hobby == 'music')
    
    OR
    from sqlalchemy import or_
    query.filter(or_(LoginInfo.name == 'zs', LoginInfo.name == 'ls'))
    
    MATCH:
    query.filter(LoginInfo.name.match('zhangsan'))
    

    Session的query函数会返回一个Query对象,

    all():返回一个对象列表循环之后直接获取对象属性即可。
    first():返回至多一个结果,而且以单项形式,而不是只有一个元素的tuple形式返回这个结果.
    one():返回且仅返回一个查询结果。当结果的数量不足一个或者多于一个时会报错。

    嵌入使用SQL

    你可以在Query中通过text()使用SQL语句。例如:

    from sqlalchemy import text
    for user in session.query(User).filter(text("id<224")).order_by(text("id")).all():
        print(user.name)
    

    除了上面这种直接将参数写进字符串的方式外,你还可以通过params()方法来传递参数

    session.query(User).filter(text("id<:value and name=:name")).
         params(value=224, name='fred').order_by(User.id).one()
    

    输出

    <User(name='fred', fullname='Fred Flinstone', password='blah')>
    

    并且,你可以直接使用完整的SQL语句,但是要注意将表名和列明写正确。

    session.query(User).from_statement(
                         text("SELECT * FROM users where name=:name")).
                        params(name='ed').all()
    

    输出

    [<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>]
    

    该部分内容来自网络。

    计数

    Query定义了一个很方便的计数函数count()

    session.query(User).filter(User.name.like('%ed')).count()
    

    等价于

    SELECT count(*) AS count_1
    FROM (SELECT users.id AS users_id,
                    users.name AS users_name,
                    users.fullname AS users_fullname,
                    users.password AS users_password
    FROM users
    WHERE users.name LIKE ?) AS anon_1
    ('%ed',)
    

    注意上面我们同时列出了实际的SQL指令。在SQLAlchemy中,我们总是将被计数的查询打包成一个子查询,然后对这个子查询进行计数。即便是最简单的SELECT count(*) FROM table,也会如此处理。为了更精细的控制计数过程,我们可以采用func.count()这个函数。

    from sqlalchemy import func
    session.query(func.count(User.name), User.name).group_by(User.name).all()
    

    等价于

    session.query(func.count(User.name), User.name).group_by(User.name).all()
    SELECT count(users.name) AS count_1, users.name AS users_name
    FROM users GROUP BY users.name
    

    为了实现最简单的SELECT count(*) FROM table,我们可以如下调用

    session.query(func.count('*')).select_from(User).scalar()
    

    等价于

    SELECT count(?) AS count_1
    FROM users
    ('*',)
    

    如果我们对User的主键进行计数,那么select_from也可以省略。

    session.query(func.count(User.id)).scalar()
    

    等价于

    SELECT count(users.id) AS count_1
    FROM users
    

    该部分内容来自网络。
    后续。。。。

  • 相关阅读:
    快速排序——中位数
    DataGridView 在下拉框添加下来事件
    VS2015 调试时 编辑并继续不可用
    用soapUI测试webservice
    SQL Server 2008 表变量 临时表
    mvc 返回值
    asp.net 页面上的点击事件
    C# SQL 面试题自我总结
    cf contest 1458
    【CFR#655】F Omkar ans Modes
  • 原文地址:https://www.cnblogs.com/c-x-a/p/9294050.html
Copyright © 2011-2022 走看看