ORM sqlachemy学习
内容:
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,表示一行记录,比如,包含id
和name
的user
表:
1 [ 2 ('1', 'woz'), 3 ('2', 'wyb'), 4 ('3', 'alex') 5 ]
Python的DB-API返回的数据结构就是像上面这样表示的,但是用tuple表示一行很难看出表的结构。
如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来:
1 class User(object): 2 def __init__(self, id, name): 3 self.id = id 4 self.name = name 5 6 [ 7 User('1', 'wyb'), 8 User('2', 'woz'), 9 User('3', 'alex') 10 ]
这就是传说中的ORM技术:Object-Relational Mapping,就是把关系数据库的表结构映射到类的对象上
但是由谁来做这个转换呢?由专业的ORM框架来做转换,Python中最有名的ORM框架是SQLAlchemy
(3)安装
1 pip3 install SQLAlchemy
3.SQLAlchemy内部处理
(1)依赖第三方
SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
1 MySQL-Python (py2语法) 2 mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> 3 4 pymysql (py3语法) 5 mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] 6 7 MySQL-Connector 8 mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> 9 10 cx_Oracle 11 oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 12 13 更多详见: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)并插入数据:
1 # __author__ = "wyb" 2 # date: 2018/8/20 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy.orm import sessionmaker 5 from sqlalchemy import ( 6 create_engine, 7 Column, 8 Integer, 9 String, 10 ) 11 12 # create_engine类似pymysql中的connect 13 # 设置echo将打印一系列过程信息 14 engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb", 15 encoding="utf-8", 16 echo=True, 17 max_overflow=5) 18 19 Base = declarative_base() # 生成ORM基类 20 21 22 # 接下来创建一个User表 23 class User(Base): 24 __tablename__ = 'user' # 表名 25 id = Column(Integer, primary_key=True) 26 name = Column(String(32)) 27 password = Column(String(64)) 28 29 30 Base.metadata.create_all(engine) # 创建表结构 31 32 33 # 接下来对表中数据进行操作 34 # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 35 Session_class = sessionmaker(bind=engine) 36 Session = Session_class() # 生成session实例(类似pymysql中的cursor) 37 38 # 生成数据对象(未创建,commit之后才创建) 39 user_obj = User(name="wyb", password="666") 40 user_obj2 = User(name="woz", password="3399") 41 Session.add(user_obj) # 把数据对象添加到session里, 后面统一创建 42 Session.add(user_obj2) # 把数据对象添加到session里, 后面统一创建 43 Session.commit() # 现此统一提交,创建数据
(2)操作表(增删改查)
1 # __author__ = "wyb" 2 # date: 2018/8/20 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy.orm import sessionmaker 5 from sqlalchemy import ( 6 create_engine, 7 Column, 8 Integer, 9 String, 10 ) 11 12 # create_engine类似pymysql中的connect 13 # 设置echo将打印一系列过程信息 14 engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb", 15 encoding="utf-8", 16 # echo=True, 17 max_overflow=5) 18 19 Base = declarative_base() # 生成ORM基类 20 Session_class = sessionmaker(bind=engine) # 创建session类 21 Session = Session_class() # 生成session实例(类似pymysql中的cursor) 22 23 24 # 接下来创建一个User表 25 class User(Base): 26 __tablename__ = 'user' # 表名 27 id = Column(Integer, primary_key=True) 28 name = Column(String(32)) 29 password = Column(String(64)) 30 31 # 直接输出查询结果 32 # __repr__是魔法方法 当直接输出User对象的实例会调用此方法 33 def __repr__(self): 34 return "<User(id='%s', name='%s', password='%s')>" % ( 35 self.id, self.name, self.password) 36 37 38 # 创建表结构 39 def create_table(): 40 Base.metadata.create_all(engine) 41 42 43 # 插入 44 def insert(user_obj): 45 print("插入数据:") 46 print(user_obj) 47 Session.add(user_obj) # 把数据对象添加到session里, 后面统一创建 48 Session.commit() # 现此统一提交,创建数据 49 50 51 # 查找 52 def select(): 53 print("查询数据:") 54 55 # 查询一条数据: 56 data = Session.query(User).filter_by(name="woz").first() # 不存在返回None 57 print("name=woz: ", data) 58 data = Session.query(User).filter_by(id=1).first() 59 print("id=1: ", data) 60 # print(my_user.id, my_user.name, my_user.password) # 输出具体值 61 62 # 查询所有数据: 63 print("表中所有数据: ", Session.query(User.id, User.name).all()) 64 65 # 多条件查询: 66 objs = Session.query(User).filter(User.id > 0).filter(User.id < 3).all() 67 # 上面2个filter的关系相当于 user.id >1 AND user.id <3 的效果 68 print("id为0到3之间的数据: ", objs) 69 70 71 # 删除 72 def delete(): 73 print("删除数据:") 74 result = Session.query(User).filter(User.name == 'alex').first() 75 print(result) 76 Session.delete(result) 77 Session.commit() 78 79 80 # 更新 81 def update(): 82 print("更新数据:") 83 my_user = Session.query(User).filter_by(name="wyb").first() 84 my_user.name = "wyb666" 85 my_user.password = "wyb666" 86 print(my_user) 87 Session.commit() 88 89 90 # 主程序 91 def main(): 92 create_table() 93 # 插入数据: 94 # insert(User(name="alex", password="3373")) 95 # 查询数据: 96 # select() 97 # update() 98 # delete() 99 100 101 if __name__ == '__main__': 102 main()
(3)回滚以及统计分组
回滚:
1 my_user = Session.query(User).filter_by(id=1).first() 2 my_user.name = "Jack" 3 4 fake_user = User(name='Rain', password='12345') 5 Session.add(fake_user) 6 7 print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) # 这时看session里有你刚添加和修改的数据 8 Session.rollback() #此时你rollback一下 9 print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) # 再查就发现刚才添加的数据没有了。 10 11 # Session.commit()
统计分组:
1 # 统计: 2 Session.query(User).filter(User.name.like("w%")).count() 3 4 # 分组 5 from sqlalchemy import func 6 print(Session.query(func.count(User.name),User.name).group_by(User.name).all() ) 7 # 相当于以下原生SQL: 8 SELECT count(user.name) AS count_1, user.name AS user_name 9 FROM user GROUP BY user.name
(4)外键关联
外键关联:
1 from sqlalchemy.ext.declarative import declarative_base 2 from sqlalchemy.orm import sessionmaker, relationship 3 from sqlalchemy import ( 4 create_engine, 5 Column, 6 Integer, 7 String, 8 ForeignKey, 9 ) 10 11 engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/wyb", 12 encoding="utf-8", 13 max_overflow=5) 14 15 Base = declarative_base() # 生成ORM基类 16 Session_class = sessionmaker(bind=engine) # 创建session类 17 Session = Session_class() # 生成session实例(类似pymysql中的cursor) 18 19 # User表 20 class User(Base): 21 __tablename__ = 'user' 22 id = Column(Integer, primary_key=True) 23 name = Column(String(32)) 24 password = Column(String(64)) 25 26 def __repr__(self): 27 return "<User(id='%s', name='%s', password='%s')>" % ( 28 self.id, self.name, self.password) 29 30 31 # Address表 32 class Address(Base): 33 __tablename__ = 'address' 34 id = Column(Integer, primary_key=True) 35 email_address = Column(String(32), nullable=False) 36 user_id = Column(Integer, ForeignKey('user.id')) # 这是外键 37 38 user = relationship("User", backref="address") # 这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项 39 40 def __repr__(self): 41 return "<Address(email_address='%s')>" % self.email_address 42 43 # 创建表结构 44 def create_table(): 45 Base.metadata.create_all(engine)
上述表创建好后,可以这样反查:
1 objs = Session.query(User).all() 2 add_objs = Session.query(Address).all() 3 for i in objs: # 通过遍历user对象反查关联的address记录 4 print(i.address) 5 for add_obj in add_objs: # 遍历add_objs里直接查关联的user对象 6 print(add_obj.user.name)
创建关联对象:
1 obj = Session.query(User).filter(User.name == 'woz').first() 2 # 查询关联对象的属性: 3 print(obj.address) 4 # 添加关联对象: 5 obj.address = [Address(email_address="wyb@126.com")] 6 Session.commit()
多外键关联:
下表中,Customer表有2个字段都关联了Address表
1 class Address(Base): 2 __tablename__ = 'address' 3 id = Column(Integer, primary_key=True) 4 street = Column(String) 5 city = Column(String) 6 state = Column(String) 7 8 class Customer(Base): 9 __tablename__ = 'customer' 10 id = Column(Integer, primary_key=True) 11 name = Column(String) 12 13 billing_address_id = Column(Integer, ForeignKey("address.id")) 14 shipping_address_id = Column(Integer, ForeignKey("address.id")) 15 16 # 这样写 会导致SQLAlchemy分不清哪个外键是对应哪个字段 会导致程序报错 17 # billing_address = relationship("Address") 18 # shipping_address = relationship("Address") 19 20 # 所以要这样写: 21 billing_address = relationship("Address", foreign_keys=[billing_address_id]) 22 shipping_address = relationship("Address", foreign_keys=[shipping_address_id])
(5)多对多联系
什么是多对多联系:学生和课程,一个课程可以有多个学生,一个学生可以有多个课程
如下所示:
1 # 多对多 2 # 一个学生可以有多个课程,一个课程可以对应多个学生 3 student_m2m_course = Table('student_m2m_course', Base.metadata, 4 Column('student_id', Integer, ForeignKey('student.id')), 5 Column('author_id', Integer, ForeignKey('course.id')), 6 ) 7 8 # 学生类 9 class Student(Base): 10 __tablename__ = 'student' 11 id = Column(Integer, primary_key=True) 12 name = Column(String(64)) 13 attach = relationship('Attach', secondary=student_m2m_course, backref='students') 14 15 def __repr__(self): 16 return "<name: %s;>" % self.name 17 18 # 课程类 19 class Course(Base): 20 __tablename__ = 'course' 21 id = Column(Integer, primary_key=True) 22 name = Column(String(32)) 23 24 def __repr__(self): 25 return "<name: %s;>" % self.name
具体操作:
1 # 关联插入 2 a1 = Student(name="12342ds") 3 a2 = Student(name="222") 4 a3 = Student(name="666") 5 6 b1 = Course(name="跟wyb学Python") 7 b2 = Course(name="跟wyb学把妹") 8 b3 = Course(name="跟wyb学装逼") 9 b4 = Course(name="跟wyb学开车") 10 11 a1.courses = [b1, b2] 12 a2.courses = [b2, b3] 13 a3.courses = [b1, b3] 14 15 Session.add_all([a1, a2, a3, b1, b2, b3, b4]) 16 Session.commit() 17 18 19 # 多对多删除 20 # 删除数据时不用管student_m2m_course这个表, sqlalchemy会自动帮你把对应的数据删除 21 student_obj = Session.query(Student).filter_by(name="12342ds").first() 22 23 course_obj = Session.query(Course).filter_by(name="跟wyb学把妹").first() 24 print(student_obj, course_obj) 25 # 以下是两种删除方法: 26 student_obj.courses.remove(course_obj) # 从课程中里删除一个学生 27 Session.delete(course_obj ) # 直接删除课程时会把这个课程和所有学生的关联关系删除 28 Session.commit()
(6)其他
处理中文:
sqlalchemy设置编码字符集一定要在数据库访问的URL上增加charset=utf8,否则数据库的连接就不是utf8的编码格式
eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
最后内容 - 今日作业:
主题:学员管理系统
需求:
- 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下
- 讲师视图
- 管理班级,可创建班级,根据学员qq号把学员加入班级
- 可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的上课纪录, 即每节课都有整班学员上, 为了纪录每位学员的学习成绩,需在创建每节上课纪录是,同时 为这个班的每位学员创建一条上课纪录
- 为学员批改成绩, 一条一条的手动修改成绩
- 学员视图
- 提交作业
- 查看作业成绩
- 一个学员可以同时属于多个班级,就像报了Linux的同时也可以报名Python一样, 所以提交作业时需先选择班级,再选择具体上课的节数
- 附加:学员可以查看自己的班级成绩排名
转载于:https://www.cnblogs.com/wyb666/p/9498154.html
ORM sqlachemy学习相关推荐
- mysql和python先学哪个_Python之路-python(mysql介绍和安装、pymysql、ORM sqlachemy)
本节内容 1.数据库介绍 2.mysql管理 3.mysql数据类型 4.常用mysql命令 创建数据库 外键 增删改查表 5.事务 6.索引 7.python 操作mysql 8.ORM sqlac ...
- ORM Bee学习捷径
ORM Bee学习捷径 到 源码官网: bee: 互联网新时代的Java ORM工具,简单.高效,开发速度快! 或(github) : GitHub - automvc/bee: Bee is an ...
- Hibernate ORM框架学习日记基础篇-1
一.简介 Hibernate是轻量级Java EE应用的持久层解决方案,不仅管理Java类库到数据库表的映射,还提供数据查询和获取数据的 方法,它完成对象模型和基于SQL的关系模型的映射关系,使得开发 ...
- python学习笔记目录
人生苦短,我学python学习笔记目录: week1 python入门week2 python基础week3 python进阶week4 python模块week5 python高阶week6 数据结 ...
- Python Day11
安装 ubuntu 14.04 sudo apt-get install -y mysql-client-5.6 mysql-common-5.6 Q1 忘记root密码 1 : sudo vi /e ...
- mysql的介绍和安装
本节内容 1.数据库介绍 2.mysql管理 3.mysql数据类型 4.常用mysql命令 创建数据库 外键 增删改查表 5.事务 6.索引 1.数据库介绍 什么是数据库? 数据库(Database ...
- django mysql orm教程_带你了解Django ORM操作(基础篇)
前言 在日常开发中,需要大量对数据库进行增删改查操作. 如果头铁的话,使用原生SQL是最好的,毕竟性能又高,又灵活. 但是通常情况下,我们不是太需要那么苛刻的性能,也没有那么多刁钻的需求用原生SQL ...
- Python学习笔记:Day 16 编写移动App
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:Day15 部署Web App
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
最新文章
- mysql ls命令,Linux 常用 ls命令详解
- IDEA中如何彻底删除项目
- eclipse制作uml_Eclipse生成一个UML
- 基于opencv的手写数字字符识别
- java POI导出多张图片到表格(占位符方式)
- 【AI-1000问】为什么现在大家喜欢用3*3小卷积?
- [翻译]XNA 3.0 Game Programming Recipes之twenty-one
- C语言学习之用牛顿迭代法求下面方程在1.5附近的根: 2x³-4x²+3x-6=0
- linux下网站服务器,Linux下使用Apache搭建Web网站服务器(示例代码)
- STM32 串口接收流程-串口接收中断
- 又一个“众所周知”的DAL层设计BUG
- html怎么实现单个li效果,JS+CSS实现的一个li:hover效果
- SQL Server 函数的使用(字符串函数)
- dos固态硬盘测试软件,dos下的硬盘检测工具MHDD图文教程!
- 用matlab求excel表中平均值,matlab如何将符合特定条件的数据导入excel并求出平均值...
- 大数据:商业革命与科学革命
- 2023 闲鱼扫码自动收货跳转支付宝HTML源码
- Linux小白的大师之路
- 如何让网页自适应所有屏幕宽度
- 划重点!关于缓冲区溢出攻击,这份防范策略一定要收好!
热门文章
- L3-016 二叉搜索树的结构 (30 分)-PAT 团体程序设计天梯赛 GPLT
- [Python] L1-007. 念数字-PAT团体程序设计天梯赛GPLT
- 蓝桥杯 ADV-188 算法提高 排列数
- Python中默认参数self的理解
- 是否遇到过MySQL workbench text字段不能直接放入json格式内容
- UnityWebform(2):自定义LifetimeManager和TypeConverter使Unity从HttpContext中取值注入WebForm页面...
- python学习(1)启程
- C++Primer第5版学习笔记(一)
- Firefox上打开的标签页太多怎么办?
- 请问如何获取字符串在数组中的位置