Python day45:ORM思想:SQLAlchemy框架---->框架的使用流程,规范/常用增删该查语句/正/反查询relationship

## SQLAlchemey

```python
SQLAlchemy是Python编程语言的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射(ORM)进行数据库操作,简言之,将对象转换成SQL,然后使用API执行SQL并获取执行结果.

安装:pip3 install SQLAlchemy
    
SQLAlchemy本身无法操作数据库,其必须以pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:    
MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
   
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
   
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
   
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
```

## ORM

```PYTHON
ORM:object relationship mapping:对象关系映射.她是一种思想,通过类及类对象转换成SQL语句创建表/操作数据,其中在python语言中SQLAlchemy是最常用的.

```

## 创建表

```python
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine
 
# 连接MySQL,创建一个链接对象 
engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/db3?charset=utf8", max_overflow=5)
#创建一个Base类,自定义的类都要继承这个类
Base = declarative_base()

class User_Type(Base):
    __tablename__="usertype"#连接数据库后,自定义类通过继承Base
    #类,在库中创建表,usertype就是表名.
    id=Column(Integer,autoincrement=True,primary_key=True)
    name=Column(String(32),nullable=False,sever_default="")
    #id,name这两个类中属性,对应的就是表中的列,属性实例化的值,就是表中每一行row的值
class User(Base):
    __tablename__="users"
    id=Column(Integer,autoincrement=True,primary_key=True)
    name=Column(String(32),nullable=False,server_default="")
    extra=Colunm(String(32),nullable=False,server_default="")
    type_id=Column(Integer,ForeignKey(User_Type.id))#创建外键
    __table_args=(UniqueConstraint("id","name",name="uix_id_name"))#创建联合唯一索引,注意格式.
    Index=("ix_name_extra","name","extra")#联合索引
    usertype=relationship("User_Type",backref="xx00")#通过relationship实现连表的正向查询,通过backref实现连表的反向查询.
    #usertype隐藏在表users中的列,这个列指向User_Type创建的表usertype中所有的列,通过实例对象row.usertype.usertype中的列名,可以实现访问(连表条件还是通过创建外键时确定的条件)
    #backref="xxoo":列名xxoo隐藏在表usertype中,类User_Type实例对象row可以通过row.xxoo.类User实例对象的属性名称,来访问User类对应的表users中的列名.

def drop_db():
    Base.metadata.drop_all(engine)
def create_db():
    Base.metadata.create_all(engine)
#通过创建函数,可以传参,如engine,不同engine,将在不同账号/不同库进行数据操作.
drop_db()
#如果要创建的表已经存在了,将不能覆盖进行创建,默认不进行创建.所以要先删除该表,再进行创建.
create_db()
 
'以下操作表中数据'
Session=sessionmaker(bind=engine)#创建一个链接数据库的会话框,类似打开一个cmd命令窗口shell,在该窗口中进行操作
session=Session()

#添加一条数据:通过实例化类,给表中的列进行添加行数据
obj=User_Type(name="普通用户")
session.add(obj)#将实例化对象转换成SQL的insert语句,在窗口中执行
session.commit()#写入数据必须需要提交!!!
#添加多条数据
session.add_all([User_Typoe(name="VIP用户"),User_Type(name="SVIP用户"),User_Type(name="MVIP用户")])
session.commint()

#查询全部:返回一个列表,列表存放的都是每一行数据所对应的python中的对象
res=session.query(User_Type).all()#User_Type类对象,表示查询类对象对应的表
'注意:res=session.query(User_Type)#这条python语句的返回结果是对应z转换的的SQL语句
for row  in res:
    print(row.id,row.name)#row是列表中的行对应的Python中的对象,通过对访问对应的值
#查询一条语句:
res=session.query(User_Type).first()#表中第一行的数据
print(res.id,res.name)#这里res返回的直接是一个对象!不再是列表等容器

'filter()过滤======>where条件筛选'
res2=session.query(User_Type).filter(User_Type.name=="VIP用户",User_Type.id==2)#返回值是一个符合条件的列表,列表元素是符合条件的对象.filter内逗号直接默认是与的关系(and_).也可以指定or关系如下:or_
res2=session.query(User_Type).filter(or_(User_Type.name=="VIP用户",User_Type.id==2))
#filter与filter_by的区别:
res=session.query(User_Type).filter_by(name="VIP用户").all()
#filter:用的是SQL语句表达式进行过滤:表名.列名=="值"
#filter_by:用的是关键字传参的语法:列名="值"

'删除':
session.query(User_Type).filter(User_Type.id>3).delete()#在SQLAlchemy中,删除/修改表中行,需要先查询再操作

'修改':
 session.query(User_Type).filter(User_Type.id>3).update({"name":"MVIP用户"})#更改数据需要传入的的数据格式是mapping类型

'MySQL高级查询操作'
#通配符/分组/排序/limit分页/between/in / ~...in(即not in)
res3=session.query(User_Type).filter(User_Type.name.like("%vip%")).all()
res3=session.query(User_Type).filter(~User_Type.name.like("%vip%")).all()#取反
#页限制 limit
res3=session.query(User_Type)[1:3]#将列表切片,[头:尾:步长]顾头不顾尾
#排序:
res3=session.query(User_Type).filter(User-Type.id>3).order_by(User_Type.name.desc()).all()#降序排序
res3=session.query(User_Type).filter(User-Type.id>3).order_by(User_Type.name.asc()).all()#升序排序
#分组:
from sqlalchemy.sql import func
res3=session.query(Users).group_by(User_Type.extra).all()
res3=session.query(User.type_id,User.id,func.max(User.id)).group_by(User.type_id).all()#显示结果以User.type_id分组,在此基础上展示query括号内的值。如果不分组或没有其他条件限制将只显示表中第一行对应的列值及表中对于的User.id对应的最大值。

#between
res3=session.query(User_Type).filter(User_Type.id.between(1,3)).all();
#in_
res4=session.query(User_Type).filter(User_Type.id.in_([1,3])).all()
#~...in_....
res4=session.query(User_Type).filter(~User_Type.id.in_([1,3])).all()

'实际应用:查询某一个用户的类型(正查询)'
#第一种方法:
res5:session.query(User,User_Type).filter(User.type_id==User_Type.id).all()#前提是先在User类中创建指向User_Type类的外键.query查询的参数必须是他们两个类,如果只是User,则只查询User类对应的表
 #第二种方法:
res5=session.query(User,User_Type).join(User_Type,isouter=True).all()#通过join中参数isouter=True,指定为左连接.但是仍需在query中指明要查询的User和User_Type.
#第三种方法:
res5=session.query(User).all()
for row in res5:
    print(row.id,row.name,row.user type.name)#usertype就是隐藏在User类对应的表中的列,因为该表已经跟User_Type对应的列建立外键,通过这个列可以访问User_Type中所有的列.这个列的声明如下:
    'usertype=relationship("User_Type")'
 

'实际应用二:查找某一个类型下的所有用户(反查询)'
#方法一:
res6=sesstion.query(User_Type).all()
for row in res6:                                   print(row.id,row.name,session.query(User.name).filter(User.type_id==row.id).all())
 #方法二:
res6=session.query(User_Type).all()
for row in res:
    print(row.id,row.name,row.xxoo)#这条语句就是反查询,是建立外键之后又usertype=relationship("User_Type",backref="xxoo"),"xxoo"可以理解为隐藏在User_Type对应表中的隐藏的列,通过该列,可以访问到User对应的表中的所有的列.

    










```

 

posted @ 2019-06-19 19:20  Python-Man  阅读(306)  评论(0编辑  收藏  举报