内容:

1.ORM介绍

2.SQLAlchemy介绍

3.SQLAlchemy内部处理

4.SQLAlchemy使用

参考:

http://www.cnblogs.com/wupeiqi/articles/5713330.html

http://www.cnblogs.com/alex3714/articles/5978329.html

廖雪峰SQLAlchemy教程

1.ORM介绍

ORM(object relational mapping),就是对象映射关系,简单来说:

对于python而已一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过ORM将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型(类和对象)进行操作就可以了,而不用直接使用sql语言。

ORM优点:

  • 隐藏了数据访问细节,“封闭”的通用数据库交互,使开发更方便快捷(数据库交互更简单)
  • ORM使我们构造固化数据结构变得简单易行

ORM缺点:

无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)

现在各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。

2.SQLAlchemy介绍

(1)什么是SQLAlchemy

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

(2)SQLAlchemy原理

数据库表是一个二维表,包含多行多列。把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含idnameuser表:

 [
('', 'woz'),
('', 'wyb'),
('', 'alex')
]

Python的DB-API返回的数据结构就是像上面这样表示的,但是用tuple表示一行很难看出表的结构。

如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来:

 class User(object):
def __init__(self, id, name):
self.id = id
self.name = name [
User('', 'wyb'),
User('', 'woz'),
User('', 'alex')
]

这就是传说中的ORM技术:Object-Relational Mapping,就是把关系数据库的表结构映射到类的对象上

但是由谁来做这个转换呢?由专业的ORM框架来做转换,Python中最有名的ORM框架是SQLAlchemy

(3)安装

 pip3 install SQLAlchemy

3.SQLAlchemy内部处理

(1)依赖第三方

SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

 MySQL-Python (py2语法)
mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql (py3语法)
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

(2)内部处理

使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句

4.SQLAlchemy使用

SQLAlchemy的使用本质上就是对其ORM功能的使用,详细说就是使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL

(1)创建表

创建一个表(user)并插入数据:

 # __author__ = "wyb"
# date: 2018/8/20
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import (
create_engine,
Column,
Integer,
String,
) # create_engine类似pymysql中的connect
# 设置echo将打印一系列过程信息
engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb",
encoding="utf-8",
echo=True,
max_overflow=5) Base = declarative_base() # 生成ORM基类 # 接下来创建一个User表
class User(Base):
__tablename__ = 'user' # 表名
id = Column(Integer, primary_key=True)
name = Column(String(32))
password = Column(String(64)) Base.metadata.create_all(engine) # 创建表结构 # 接下来对表中数据进行操作
# 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
Session_class = sessionmaker(bind=engine)
Session = Session_class() # 生成session实例(类似pymysql中的cursor) # 生成数据对象(未创建,commit之后才创建)
user_obj = User(name="wyb", password="")
user_obj2 = User(name="woz", password="")
Session.add(user_obj) # 把数据对象添加到session里, 后面统一创建
Session.add(user_obj2) # 把数据对象添加到session里, 后面统一创建
Session.commit() # 现此统一提交,创建数据

(2)操作表(增删改查)

 # __author__ = "wyb"
# date: 2018/8/20
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import (
create_engine,
Column,
Integer,
String,
) # create_engine类似pymysql中的connect
# 设置echo将打印一系列过程信息
engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb",
encoding="utf-8",
# echo=True,
max_overflow=5) Base = declarative_base() # 生成ORM基类
Session_class = sessionmaker(bind=engine) # 创建session类
Session = Session_class() # 生成session实例(类似pymysql中的cursor) # 接下来创建一个User表
class User(Base):
__tablename__ = 'user' # 表名
id = Column(Integer, primary_key=True)
name = Column(String(32))
password = Column(String(64)) # 直接输出查询结果
# __repr__是魔法方法 当直接输出User对象的实例会调用此方法
def __repr__(self):
return "<User(id='%s', name='%s', password='%s')>" % (
self.id, self.name, self.password) # 创建表结构
def create_table():
Base.metadata.create_all(engine) # 插入
def insert(user_obj):
print("插入数据:")
print(user_obj)
Session.add(user_obj) # 把数据对象添加到session里, 后面统一创建
Session.commit() # 现此统一提交,创建数据 # 查找
def select():
print("查询数据:") # 查询一条数据:
data = Session.query(User).filter_by(name="woz").first() # 不存在返回None
print("name=woz: ", data)
data = Session.query(User).filter_by(id=1).first()
print("id=1: ", data)
# print(my_user.id, my_user.name, my_user.password) # 输出具体值 # 查询所有数据:
print("表中所有数据: ", Session.query(User.id, User.name).all()) # 多条件查询:
objs = Session.query(User).filter(User.id > 0).filter(User.id < 3).all()
# 上面2个filter的关系相当于 user.id >1 AND user.id <3 的效果
print("id为0到3之间的数据: ", objs) # 删除
def delete():
print("删除数据:")
result = Session.query(User).filter(User.name == 'alex').first()
print(result)
Session.delete(result)
Session.commit() # 更新
def update():
print("更新数据:")
my_user = Session.query(User).filter_by(name="wyb").first()
my_user.name = "wyb666"
my_user.password = "wyb666"
print(my_user)
Session.commit() # 主程序
def main():
create_table()
# 插入数据:
# insert(User(name="alex", password="3373"))
# 查询数据:
# select()
# update()
# delete() if __name__ == '__main__':
main()

(3)回滚以及统计分组

回滚:

 my_user = Session.query(User).filter_by(id=1).first()
my_user.name = "Jack" fake_user = User(name='Rain', password='')
Session.add(fake_user) print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) # 这时看session里有你刚添加和修改的数据
Session.rollback() #此时你rollback一下
print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) # 再查就发现刚才添加的数据没有了。 # Session.commit()

统计分组:

 # 统计:
Session.query(User).filter(User.name.like("w%")).count() # 分组
from sqlalchemy import func
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() )
# 相当于以下原生SQL:
SELECT count(user.name) AS count_1, user.name AS user_name
FROM user GROUP BY user.name

(4)外键关联

外键关联:

 from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import (
create_engine,
Column,
Integer,
String,
ForeignKey,
) engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb",
encoding="utf-8",
max_overflow=5) Base = declarative_base() # 生成ORM基类
Session_class = sessionmaker(bind=engine) # 创建session类
Session = Session_class() # 生成session实例(类似pymysql中的cursor) # User表
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(32))
password = Column(String(64)) def __repr__(self):
return "<User(id='%s', name='%s', password='%s')>" % (
self.id, self.name, self.password) # Address表
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email_address = Column(String(32), nullable=False)
user_id = Column(Integer, ForeignKey('user.id')) # 这是外键 user = relationship("User", backref="address") # 这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项 def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address # 创建表结构
def create_table():
Base.metadata.create_all(engine)

上述表创建好后,可以这样反查:

1 objs = Session.query(User).all()
add_objs = Session.query(Address).all()
for i in objs: # 通过遍历user对象反查关联的address记录
print(i.address)
for add_obj in add_objs: # 遍历add_objs里直接查关联的user对象
print(add_obj.user.name)

创建关联对象:

 obj = Session.query(User).filter(User.name == 'woz').first()
# 查询关联对象的属性:
print(obj.address)
# 添加关联对象:
obj.address = [Address(email_address="wyb@126.com")]
Session.commit()

多外键关联: 

下表中,Customer表有2个字段都关联了Address表

 class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
street = Column(String)
city = Column(String)
state = Column(String) class Customer(Base):
__tablename__ = 'customer'
id = Column(Integer, primary_key=True)
name = Column(String) billing_address_id = Column(Integer, ForeignKey("address.id"))
shipping_address_id = Column(Integer, ForeignKey("address.id")) # 这样写 会导致SQLAlchemy分不清哪个外键是对应哪个字段 会导致程序报错
# billing_address = relationship("Address")
# shipping_address = relationship("Address") # 所以要这样写:
billing_address = relationship("Address", foreign_keys=[billing_address_id])
shipping_address = relationship("Address", foreign_keys=[shipping_address_id])

(5)多对多联系 

什么是多对多联系:学生和课程,一个课程可以有多个学生,一个学生可以有多个课程

如下所示:

 # 多对多
# 一个学生可以有多个课程,一个课程可以对应多个学生
student_m2m_course = Table('student_m2m_course', Base.metadata,
Column('student_id', Integer, ForeignKey('student.id')),
Column('author_id', Integer, ForeignKey('course.id')),
) # 学生类
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True)
name = Column(String(64))
attach = relationship('Attach', secondary=student_m2m_course, backref='students') def __repr__(self):
return "<name: %s;>" % self.name # 课程类
class Course(Base):
__tablename__ = 'course'
id = Column(Integer, primary_key=True)
name = Column(String(32)) def __repr__(self):
return "<name: %s;>" % self.name

具体操作:

 # 关联插入
a1 = Student(name="12342ds")
a2 = Student(name="")
a3 = Student(name="") b1 = Course(name="跟wyb学Python")
b2 = Course(name="跟wyb学把妹")
b3 = Course(name="跟wyb学装逼")
b4 = Course(name="跟wyb学开车") a1.courses = [b1, b2]
a2.courses = [b2, b3]
a3.courses = [b1, b3] Session.add_all([a1, a2, a3, b1, b2, b3, b4])
Session.commit() # 多对多删除
# 删除数据时不用管student_m2m_course这个表, sqlalchemy会自动帮你把对应的数据删除
student_obj = Session.query(Student).filter_by(name="12342ds").first() course_obj = Session.query(Course).filter_by(name="跟wyb学把妹").first()
print(student_obj, course_obj)
# 以下是两种删除方法:
student_obj.courses.remove(course_obj) # 从课程中里删除一个学生
Session.delete(course_obj ) # 直接删除课程时会把这个课程和所有学生的关联关系删除
Session.commit()

(6)其他

处理中文:

sqlalchemy设置编码字符集一定要在数据库访问的URL上增加charset=utf8,否则数据库的连接就不是utf8的编码格式

eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)

最后内容 - 今日作业:

主题:学员管理系统

需求:

  • 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下
  • 讲师视图
    1.   管理班级,可创建班级,根据学员qq号把学员加入班级
    2.   可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的上课纪录, 即每节课都有整班学员上, 为了纪录每位学员的学习成绩,需在创建每节上课纪录是,同时         为这个班的每位学员创建一条上课纪录
    3.   为学员批改成绩, 一条一条的手动修改成绩
  • 学员视图
  1. 提交作业
  2. 查看作业成绩
  3. 一个学员可以同时属于多个班级,就像报了Linux的同时也可以报名Python一样, 所以提交作业时需先选择班级,再选择具体上课的节数
  4. 附加:学员可以查看自己的班级成绩排名

ORM sqlachemy学习的更多相关文章

  1. Python之路-python(mysql介绍和安装、pymysql、ORM sqlachemy)

    本节内容 1.数据库介绍 2.mysql管理 3.mysql数据类型 4.常用mysql命令 创建数据库 外键 增删改查表 5.事务 6.索引 7.python 操作mysql 8.ORM sqlac ...

  2. ORM sqlachemy

    本节内容 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业 1. ORM介绍 orm英文全称object relational mapping ...

  3. ORM PHP 学习记录

    ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射.为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却 ...

  4. ORM框架学习之EF

    首先推荐一篇很好的EF文章翻译,可以系统的学习一遍. <Entity Framework 6 Recipes>中文翻译系列 EF使用体会 优点: 可以省去Ado.net复杂的管道连接代码. ...

  5. python中orm框架学习

    安装sqlalchemy pip3 install sqlalchemy 创建表结构: from sqlalchemy import Column,String,create_engine from ...

  6. 转:C#制作ORM映射学习笔记三 ORM映射实现

    现在开始实现ORM的主体模块,首先需要在项目中新建一个类,命名为DbAccess,然后在项目的引用中添加两个dll,分别是MySql.Data.dll和System.Data.SQLite.dll,这 ...

  7. 转:C#制作ORM映射学习笔记二 配置类及Sql语句生成类

    在正式开始实现ORM之前还有一点准备工作需要完成,第一是实现一个配置类,这个很简单的就是通过静态变量来保存数据库的一些连接信息,等同于.net项目中的web.config的功能:第二需要设计实现一个s ...

  8. 转:C#制作ORM映射学习笔记一 自定义Attribute类

    之前在做unity项目时发现只能用odbc连接数据库,感觉非常的麻烦,因为之前做web开发的时候用惯了ORM映射,所以我想在unity中也用一下ORM(虽然我知道出于性能的考虑这样做事不好的,不过自己 ...

  9. SqlSugar ORM 的学习

    http://www.codeisbug.com/Doc/8/1163 https://www.cnblogs.com/sunkaixuan/p/6082664.html

随机推荐

  1. TensorRT简介-转载

    前言 NVIDIA TensorRT是一种高性能神经网络推理(Inference)引擎,用于在生产环境中部署深度学习应用程序,应用有 图像分类.分割和目标检测等,可提供最大的推理吞吐量和效率.Tens ...

  2. Maven项目中的配置

    1 在配置好Maven项目后,新建一个Maven Project.如图 点击next,会进入如下界面: 选择webapp,不选择默认的quickstart,之后会进入以下界面 填好Group ID 和 ...

  3. ElasticSearch(八):springboot集成ElasticSearch集群并使用

    1. 集群的搭建 见:ElasticSearch(七) 2. springboot配置集群 2.1 创建springboot项目,使用idea创建,不过多介绍(创建项目时候建议不要勾选elastics ...

  4. mvc之URL篇

    一.根据路由系统生成友好的URL ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName); 会根据当前的路 ...

  5. test20181004 苹果树

    题意 分析 对每个点维护子树所能达到的dfn最大值.最小值.次大值.次小值,然后就可以计算原树中每个点与父亲的连边对答案的贡献. 如果子树中没有边能脱离子树,断掉该边与任意一条新加的边都成立,答案就加 ...

  6. Android USB gadget框架学习笔记

    一 Gadget框架结构 kernel/drivers/usb/gadget,这个目录是android下usbgadget的主要目录. Gadget功能组织单元:主要文件android.c,usb g ...

  7. day26 python学习 对象的接口,封装,私用属性 property

    # 抽象类和接口类 #** #不崇尚接口类 #python本身支持多继承,没有接口专用的语法.但是我知道接口的概念 # 接口类:# 是规范子类的一个模板,只要接口类中定义的,就应该在子类中实现# 接口 ...

  8. 【转】每天一个linux命令(21):find命令之xargs

    原文网址:http://www.cnblogs.com/peida/archive/2012/11/15/2770888.html 在使用 find命令的-exec选项处理匹配到的文件时, find命 ...

  9. Nginx 下部署 HTTPS 与安全调优

    什么是 HTTPS?# HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的 ...

  10. virtualbox安装增强功能并设置共享文件夹

    virtualbox安装增强功能并设置共享文件夹 我们在安装之前,必须得先安装好它所需要的依赖包,不然安装过程必定会出现错误! 一.安装依赖包 #yum install kernel-headers# ...