1.安装sqlalchemy及配置数据库

1.1安装插件

# 在terminal中进行插件安装
pip install sqlalchemy # 安装sqlalchemy,这是一个基于pymysql的框架
pip install pymysql  # 安装pymysql,该插件是直接链接数据库的基础

1.2配置数据库参数

# 配置数据库
from  sqlalchemy import create_engine  #导入创建引擎的类
# 数据库相关参数配置
HOSTNAME='localhost'  # mysql数据库服务器的地址,这里以本机地址为例
PORT = '3306'  # 默认端口3306
USERNAME = 'root'  # 登录数据库的用户,这里以'root'用户为例
PASSWORD = 'password' # 登录数据库的密码 (这里写的是明码,注意在具体开发的时候应该不能这么干,后续想想怎么处理)
DATABASE = 'database_name' # 选中数据库
DB_URI ='mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)  # 对数据库配置参数进行结构化(这里的结构适用于sqlalchemy)

1.3建立链接及执行原生sql语句

# 根据数据库配置参数DB_URI,利用sqlalchemy的create_engine,创建一个引擎,这里命名为engine.
engine = create_engine(DB_URI)
# 使用with语句连接数据库,进行数据库操作,如果发生异常会被捕获.另外在pymsyql中,执行完数据库操作之后,会手动关闭游标和链接,而with语句不需要,会自动关闭
with engine.connect () as con: # 建立与数据库之间的链接(这里笔者的理解是,con相当于pymysql中的cursor,但是又有区别,cursor执行完sql语句之后会将数据保存在cursor游标中,而这里con在执行完查询语句后,会直接将数据返回)
	con.execute('drop table if exists authors') # 删除名叫authors的数据表
	con.execte('create table authors(id int primary key auto_increment,name varchar(25))') # 创建一个表authors,包含主键字段id,普通字段name
	con.execute('insert into authors(name) values("abc")')# 插入一条记录,注意引号的包含关系
	data = con.execute('select * from authors') # 这里的data是一个class模型
	# print(type(data)) -->  <class 'sqlalchemy.engine.result.RultProxy'> 这东西竟然还是一个类,暂时只能记其书写格式,和执行结果
	# 遍历输出结果
	for results in results:
		print(results)  # 每条记录的数据输出的结果是元组(value1,value2...),对应着user表的字段.
# 上述的删,建,增,查是基于原生的sql语句,即sqlalchemy支持执行原生sql语句,但是,这并不是sqlalchemy的G点

2.ORM框架(两条腿:数据模型&session对象)

  • 使用ORM框架来操作数据库,首先需要创建一个类(第一条腿:模型)来与对应的数据表进行映射
from sqlalchemy import create_ingine, Cloumn,Integer,String
from sqlalchemy.ext.declarative import declarative_base # 导入创建Base类的基类,(字面意思:声明基础)
# 这里需要配置DB_URI,过程同前,一般情况下,DB_URI的配置,放在一个单独的文件中,用的时候直接导入.
from constants import DB_URI
engine = create_engine(DB_URI,echo=True)
Base = declarative_base(engine)  # declarative_base是一个基类,用来创建表,以及实例化表中的记录数据(从以上的过程做冲可以看出,最开始的数据库配置参数,一直被传递着,流程为:DB_URI-->create_ingine(UB_URI)-->declarative_base(create_ingine(UB_URI)),但是Base是一个类.将来所有的模型类及数据记录对象中都接受有着这样的数据库参数.
class User(Base): # 这里User模型继承自Base基类,也就是说User模型中也包含数据库链接的参数
	# 定义表名为users
	__tablename__='users' # 
	# 增加id字段,将id设置为主键,并且默认是自增长的
	id = Cloumn(Integer,primary_key=True)# Cloumn String Iteger...需要导入
	name = Cloumn(String(50))
	fullname = Cloumn(String(50))
	password = Cloumn(100)
	# 格式化输出字符串方法,__pripr__该魔术方法,当对象被打印或者返回时,自动返回一个字符串.
	def __prepr__(self):
		return "<User(id='%s',name='%s',fullname='%s',password='%s')>"%(self.id,self.name,self.fullname.self.password)

Base.metadata.create_all() # 这里有一点不太明白为什么使用父类Base调用其方法进行创建数据表.底层不是很理解,注意这里只映射一次
  • 补充:SQLALchemy会自动设置第一个Integer类型并且没有被标记为外键的主键为自增型的.
  • 基于ORM框架的增删改查(使用sessionmaker,创建ORM的另一条腿session对象)
  • 增(其实是实例化一个对象,用对象暂存数据,最后一次性录入到数据表中)
# 这里实例化了一个user对象,将数据保存到属性中,但是还没有保存到数据库中
user1 = User(name='name1',fullname='name_full',password='123')
from sqlalchemy.orm import sessionmaker
session = sessionmaker(bind=engine)() # 这里需要注意,sessionmaker也是一个基类,session是一个对象,所有的增删改查,最终都需要通过session对象完成,这里可以发现session是与engine有关的,也就是与之前链接的数据库有关联
session.add(user1)  # 值得注意的是,session的add操作是基于对象进行的,将对象作为参数,最终提交到数据库.
session.commit() # 调用session中的commit方法,完成最终的提交动作
session.delete(object)# object对象是数据表中的一条记录,对象本身含有其在数据库中的位置,所有直接执行就ok了
session.commit() # 注意删除后记得提交
object.field=new_value# object是数据对象,field是对应的字段(属性),相当于给属性赋了一个新的值,此为更新
session.commit() # 提交更新
session.query(class/class.field)[.filter()][.first()/all()] # 查询的时候,可以使用模型参数,也可以使用类名.字段名(获取想要的字段的值)

3.SQLALchemy中的常用参数

3.1建表语句Cloumn

• default:默认值
• mullable:是否可空 False | True
• primary_key: 是否为主键 False | True
• unique:是否唯一 False | True
• autoinrement: 是否自增长False | True
• onupdate :更新时候执行的语句???
• name:该属性在数据库中的字段映射???

3.2sqlalchemy常用数据类型

• Integer:整形
• Float:浮点型
• Boolean:布尔型数据
• DECIMAL:定点类型,精度确定
• enum:枚举类型
• Date:传递datetime.date()进行
• DateTime:传递datetime.datetime()进去
• Time:传递datetime.time()进去.
• String:字符类型,使用时跟上长度String(20),区别与text类型
• Text:文本类型
• LONGTEXT:长文本类型

3.3query可用参数

  • 1.模型对象(类名,继承自declarative_base(engine)()).指定查找这个模型中所有的对象(包含的属性就是数据)
  • 2.模型中的属性.可以指定数据表的字段进行查找
  • 3.from sqlalchemy import func (func是聚合函数)
• func.count:统计对象个数的函数
• func.avg:求平均值
• func.max:求最大值
• func.min:求最小值
• func.sum:求和

3.4过滤条件

  • 过滤

(1)equals: ==

query.filter(User.name == 'aname')

(2)not equals: !=

query.filter(User.name != 'aname')

(3)like:(模糊匹配)

query.filter(User.name.like('%ed%'))  # 这么写的正则意义是 匹配name字段的值包含ed的所有记录.

(4)in:

query.filter(User.name.in_(['ed','wendy','jack']))  # in后面这里跟的是一个列表,也可以跟一个查询语句,因为查询语句的结果就是一个列表

(5)not in:

query.filter(~User.name.in_(['ed','wendy','jack']))  # 这么写的正则意义是 匹配name字段的值包含ed的所有记录.

(6)is null:

query.filter(User.name == None)
# or
query.filter(User.name.is_(None))

(7)is not null:

session.query.filter(User.name !=None)
# 或者是
session.query.filter(User.name.isnot(None))

(8)and:

from sqlalchemy import and_
sesstion.query.filter(and_(User.name == 'aname',User.fullname == 'afullname')) # 条件与操作

(9)or:

from sqlalchemy import or_
sesstion.query.filter(or_(User.name == 'aname',User.fullname == 'afullname')) # 条件与操作

(10)and or 的复合条件过滤

from sqlalchemy import and_,or_
sesstion.query.filter(and_(User.name == 'aname',User.fullname == 'afullname')).filter(or_(condition1,condition2)) # 条件与&或的综合操作,其含义是条件过滤后的列表,可以继续进行条件过滤

sqlalchemy中其他常用关键字

1.expunge(提交前删除session中对象)

user = User(...) # 创建一个对象
session.add(user) # 添加一个对象到session对象中
session.expunge(user) # 从session对象中删除user对象
session.commit()  # 此时session提交的结果中,没有user这条记录

2.order_by

# 首先需要在模型当中添加属性__mapper_args__ = {'order_by':[-]字段名},[-]表示倒序.在数据录入的时候,数据表中的记录会自动根据这个字段进行排序录入
# 其次在查询该模型映射的表时候
objects = session.query(classname).order_by(classname.field.desc()).all()# 表示从classname映射的表中查询记录,按照field字段降序排列,并全部取出.

3.懒加载lazy = ‘dynamic’

# 懒加载是指,在建立关系映射模型的时候,在建立连接的relationship语句中,增加lazy='dynamic'这个参数
 author = relationship("User",backref=backref("articles",lazy='dynamic'))
 # 这是一个1对多关系.这个时候,通过User模型的对象调用属性articles,并不会直接返回相关对象组成的列表,而是返回一个查询语句,这个语句可以做进一步的过滤等操作,最终可以通过.all()/.first()/.last()将对象组成的列表展示出来.

4.group_by & having

# eg:
result = session.query(Users.age,func.count(Users.id)).group_by(Users.age).having(Users.age>25).all() # group_by,having的固定用法,其意义与sal原生语句作用一致,按照User.age.进行分组,且在query()语句中只能出现一个字段User.age,这一点与sql语句中的一致.having是分组后的条件过滤语句

5.显式内连接进行关联查询(join)

# eg:
result = session.query(A,func.count(B.id)).join(B).group_by(A.id).order_by(func.count(B.id).desc()).all()
# 上述例子对应的原生mysql语句为:
select A.id,count(B.id) from A join B on A.id = B.uid group by A.id order by count(B.id) desc

6.子查询

# 所谓子查询,就是用查询结果得到的对象,或这对象组成的列表作为结果集或者对象的某个字段值作为条件进行二次查询.(与mysql中子查询的概念一致)