本章内容

  1. ORM介绍
  2. sqlalchemy安装
  3. sqlalchemy基本使用
  4. 多外键关联
  5. 多对多关系
  6. 表结构设计作业

ORM介绍

  如果写程序用pymysql和程序交互,那是不是要写原生sql语句。如果进行复杂的查询,那sql语句就要进行一点一点拼接,而且不太有重用性,扩展不方便。而且写的sql语句可能不高效,导致程序运行也变慢。
为了避免把sql语句写死在代码里,有没有一种方法直接把原生sql封装好了并且以你熟悉的方式操作,像面向对象那样?

  ORM(object relational mapping),就是对象映射关系程序,简单来说我们类似Python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。

  ORM 相当于把数据库也给你实例化了,在代码操作MySQL中级又加了orm这一层。

  

  ORM的优点:

  1. 隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
  2. ORM使我们构造固化数据结构变得简单易行。

  缺点:

  1. 无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。

sqlalchemy安装

  在python中,最有名的ORM框架是SQLAlchemy。用户包括OpenStack\Dropbox等知名公司或应用,主要用户列表http://www.sqlalchemy.org/organizations.html#openstack

  安装sqlalchemy

 pip install SQLAlchemy
pip install pymysql
# 由于mysqldb依然不支持py3,所以这里我们用pymysql与sqlalchemy交互
# 虽然大家可能在python2.x中用习惯了mysqldb,但是在python3.x中已经不支持那个组件了。取而代之的是:pymysql

sqlalchemy基本使用

  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...]

  基本的增、删、改、查

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker Base = declarative_base() class User(Base):
__tablename__ = 'user' #表名
id = Column(Integer, primary_key=True)
username = Column(String(100))
password = Column(String(100))
    #定义函数的输出方式,不然会以对象的形式输出,<__main__.User object at 0x105b4ba90>
   def __repr__(self):
       return  'name:%s,password:%s'%(self.username,self.password)

 #创建实例并连接数据库
engine = create_engine("mysql+mysqldb://woniu:1234@59.110.12.72:3306/wangjin?charset=utf8",echo=True) #echo 输出日志的信息
# 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
db_session = sessionmaker(bind=engine) # 实例和engine绑定
session = db_session() # 生成session实例,相当于游标 #add user
user_obj = User(username='hello',password='python') # 生成你要创建的数据对象
session.add(user_obj) # 把要创建的数据对象添加到这个session里
session.commit()
print user_obj.username
print user_obj.password #现此才统一提交,创建数据 #query
my_user = session.query(User).filter_by(username='hello').first() #根据条件去查询 print my_user.username,my_user.password #edit
edit_user = session.query(User).filter_by(username='hello').all()
edit_user.username = 'woniu' #赋值
edit_user.password = 'hehe' session.commit()
print my_user.username,my_user.password #del
del_user = session.query(User).filter_by(username='hello').all()
for i in del_user:
session.delete(i)
session.commit()
 #rallback
my_user = Session.query(User).filter_by(id=1).first()
my_user.name = "Jack" fake_user = User(name='Rain', password='12345')
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
# Session.commit()

   filter_by与filter的区别

my_user2 = Session.query(User).filter_by(id=27).all() # filter_by相等用‘=’   

my_user3 = Session.query(User).filter(User.id==27).all() # filter相等用‘==’

用法不同而已,filter 可以像写 sql 的 where 条件那样写 > < 等条件,但引用列名时,需要通过 类名.属性名 的方式。 filter_by 可以使用 python 的正常参数传递方法传递条件,指定列名时,不需要额外指定类名。,参数名对应名类中的属性名

   多条件查询

   objs = Session.query(User).filter(User.id>0).filter(User.id<7).all()

   上面2个filter的关系相当于 user.id >1 AND user.id <7 的效果

        from sqlalchemy import and_, or_ # 且和or的关系

        ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all() # 条件以and方式排列

        ret = session.query(Users).filter(or_(Users.id < 2, Users.name == 'eric')).all() # 条件以or方式排列

  分组统计 

from sqlalchemy import func
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() ) Session.query(User).filter(User.name.like("Ra%")).count().all() #输出结果
4
[(1, 'alex'), (1, 'chongyang'), (4, 'liming')

外键关联

import sqlalchemy

from sqlalchemy import create_engine,func,ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker,relationship engine = create_engine("mysql+pymysql://woniu:123456@59.110.12.72/txadmin",encoding='utf-8') Base = declarative_base() class Student(Base):
__tablename__ = 'student'
id = Column(Integer,primary_key=True)
name = Column(String(32))
password = Column(String(64)) def __repr__(self):
return 'name:%s,password:%s'%(self.name,self.password) class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer,primary_key=True)
email_address = Column(String(32),nullable=False)
user_id = Column(Integer,ForeignKey('student.id'))

#允许你在student表里通过backref字段反向查出所有它在addresses表里的关联项
student = relationship('Student',backref='addresses') def __repr__(self):
return 'Address(email_address="%s")'%self.email_address Base.metadata.create_all(engine) db_session = sessionmaker(bind=engine)
session = db_session() #add user
# user_obj = Student(name = 'alex',password='1234')
# session.add(user_obj)
# session.commit()
# print(user_obj.name)
# print(user_obj.password)
# 如果有多个对象需要添加,可以如下使用
session.add_all([obj1,obj2,obj3])
#add_address
# add_obj = Address(email_address = 'hebeisheng',user_id = '2')
# session.add(add_obj)
# session.commit()
# #query
# # my_user = session.query(Student).filter_by(name='liming').all()
# res = session.query(func.count(Student.name),Student.name).group_by(Student.name).all()
#
# res1 = session.query(Student).filter(Student.name.like('li%')).count()
# print(res1)
# print(res) # obj = session.query(Student).all()
#
#
# for i in obj:
# print(i.addresses)

#在addr_obj里直接插关联的student表
# addr_obj = session.query(Address).all()
# for i in addr_obj:
# print(i.student.name)

#通过student对象方差关联的address的记录
obj = session.query(Student).filter_by(name='liming').all()[2]
print(obj.addresses)

#添加关联对象
obj.addresses = [Address(email_address="r1@126.com"),Address(email_address="8888888.com")]
session.commit()
print(obj.addresses) #运行结果
[]
[Address(email_address="r1@126.com"), Address(email_address="8888888.com")] #首先 第三个李明是没有设置对应的地址的,所以为空,设置完毕后就可以看到对应的值了

多外键关联

  customer 表中的 billing_address_id 关联 address表的ID

  customer 表中的 shipping_address_id 关联 address表的ID

 import sqlalchemy
from sqlalchemy import Integer,Column,String,ForeignKey,create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship,sessionmaker engine = create_engine("mysql+pymysql://woniu:123456@59.110.12.72/txadmin",encoding='utf-8')
Base = declarative_base() class Customer(Base):
__tablename__ = 'customer'
id = Column(Integer,primary_key=True)
name = Column(String(32)) billing_address_id = Column(Integer,ForeignKey('address.id')) #建立外键
shipping_address_id = Column(Integer,ForeignKey('address.id')) #建立外键 billing_address = relationship('Address',foreign_keys=[billing_address_id]) #注意这两行
shipping_address = relationship('Address',foreign_keys=[shipping_address_id]) # def __repr__(self):
# return '{name:%s,billing_addres:%s,shipping_address:%s}'%(self.name,self.billing_address,self.shipping_address) class Address(Base):
__tablename__ = 'address'
id = Column(Integer,primary_key=True)
street = Column(String(32))
city = Column(String(32))
state = Column(String(32)) def __repr__(self):
return self.city Base.metadata.create_all(engine) db_session = sessionmaker(bind=engine)
session = db_session() # obj2 = Address(street = 'shipping_address',city='test',state='eee')
# obj3 = Address(street = 'billing_address',city='test',state='eee')
# session.add(obj2)
# session.add(obj3)
#
# session.commit()
#
#
# obj = Customer(name = 'nima',billing_address = obj2,shipping_address = obj3)
# session.add(obj)
# session.commit() res = session.query(Customer).filter(Customer.name == 'nima').first()
print(res.name,dir(res))
print(res.billing_address,res.shipping_address) #可以关联得到外键,通过customer表,查看address表

多外键

mysql> desc address;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| street | varchar(32) | YES | | NULL | |
| city | varchar(32) | YES | | NULL | |
| state | varchar(32) | YES | | NULL | |
+--------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec) mysql> desc customer;
+---------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | YES | | NULL | |
| billing_address_id | int(11) | YES | MUL | NULL | |
| shipping_address_id | int(11) | YES | MUL | NULL | |
+---------------------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec) mysql> select * from customer;
+----+---------+--------------------+---------------------+
| id | name | billing_address_id | shipping_address_id |
+----+---------+--------------------+---------------------+
| 6 | liming | 6 | 7 |
| 7 | xiaohua | 4 | 5 |
| 8 | xiaohua | 4 | 5 |
| 9 | xiaohua | 14 | 15 |
| 10 | nima | 16 | 17 |
+----+---------+--------------------+---------------------+
5 rows in set (0.01 sec) mysql> select * from address;
+----+------------------+------+-------+
| id | street | city | state |
+----+------------------+------+-------+
| 3 | uuu | rrr | eee |
| 4 | shipping_address | rrr | eee |
| 5 | shipping_address | rrr | eee |
| 6 | shipping_address | rrr | eee |
| 7 | billing_address | rrr | eee |
| 8 | shipping_address | qqq | eee |
| 9 | billing_address | www | eee |
| 10 | shipping_address | qqq | eee |
| 11 | billing_address | www | eee |
| 12 | shipping_address | qqq | eee |
| 13 | billing_address | www | eee |
| 14 | shipping_address | test | eee |
| 15 | billing_address | test | eee |
| 16 | shipping_address | test | eee |
| 17 | billing_address | test | eee |
+----+------------------+------+-------+
15 rows in set (0.00 sec) mysql>

mysql 表信息

返回mysql目录

Python ORM的更多相关文章

  1. python/ORM操作详解

    一.python/ORM操作详解 ===================增==================== models.UserInfo.objects.create(title='alex ...

  2. Django和SQLAlchemy,哪个Python ORM更好?

    ORM是什么? 在介绍Python下的两个ORM框架(Django和SQLAlchemy)的区别之前,我们首先要充分了解ORM框架的用途. ORM代表对象关系映射.ORM中的每个单词解释了他们在实际项 ...

  3. Python ORM框架之 Peewee入门

    之前在学Django时,发现它的模型层非常好用,把对数据库的操作映射成对类.对象的操作,避免了我们直接写在Web项目中SQL语句,当时想,如果这个模型层可以独立出来使用就好了,那我们平台操作数据库也可 ...

  4. python orm框架

    #!/usr/bin/python# -*- coding: utf-8 -*-from sqlalchemy import create_enginefrom sqlalchemy import T ...

  5. MySQL(Python+ORM)

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...

  6. Python ORM框架之SQLAlchemy

    前言: Django的ORM虽然强大,但是毕竟局限在Django,而SQLAlchemy是Python中的ORM框架: SQLAlchemy的作用是:类/对象--->SQL语句--->通过 ...

  7. Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍

    1. 添加一个新对象 前面介绍了映射到实体表的映射类User,如果我们想将其持久化(Persist),那么就需要将这个由User类建立的对象实例添加到我们先前创建的Session会话实例中: 复制代码 ...

  8. python ORM - sqlalchemy 操作使用

    python操作数据库 使用 ORM - sqlalchemy,pymsql 安装: pip install pymsq pip install sqlalchemy 一. '''连接数据库'''   ...

  9. python orm / 表与model相互转换

    orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的 ...

随机推荐

  1. Unity3d发布apk文件并在Android虚拟机中运行的操作流程

    总的流程分为以下6个步骤: 1.安装java_jdk 2.配置java环境变量 3.更新android的sdk 4.从Unity3d中发布出apk文件 5.创建android虚拟机并运行 6.将apk ...

  2. webpack.config.js====CSS相关:postcss-loader加载器,自动添加前缀

    1. 在webpack中加载css需要先安装style-loader 和 css-loader cnpm install --save-dev style-loader css-loader 2. 在 ...

  3. webpack相关插件

    webpack-merge:开发环境和生产环节的webpaak配置文件的配置合并 file-loader:编译写入文件,默认情况下生成文件的文件名是文件名与MD5哈希值的组合 vue-laoder:编 ...

  4. JavaScprit30-6 学习笔记

    今天学习的是  仿即时搜索诗句效果 第一个问题: fetch() Fetch API  提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应.它还提供了一个全局 fe ...

  5. (2017.10.10) 我对 JavaScript 历史的认识

    关于 JavaScript 的历史和来由相信学过 JavaScript 的小伙伴都能说出一二.我看过一些入门书籍第一章或者前言部分都有介绍,但是一直没捋清这段历史.今天通过两个问题,来加深我对 Jav ...

  6. 【extjs6学习笔记】1.1 初始:创建项目

    创建工作空间 sencha generate workspace /path/to/workspace 使用sencha创建应用 sencha -sdk /path/to/sdk generate a ...

  7. SqlServer中生成一串连续数字

    在SQLServer中一串连续数字,如1,2,3,4,5,....或者 1 2 3 4 5 没有现成方法,网上都用通用表表达式递归生成.今天想到一个还算简单的方法,记录下来: select row_n ...

  8. Modelsim与Simulink协同仿真

    当使用硬件描述语言(HDL)完成电路设计时,往往需要编写Testbench对所设计的电路进行仿真验证,测试设计电路的功能是否与预期的目标相符.而编写Testbench难度之大,这时可以借助交互式图形化 ...

  9. C++容器类-list

    C++ 表(List容器类) 一.概念 头文件:#include <list> 又叫链表,是一种双线性链表,只能顺序访问(从前往后或从后往前) 他不支持随机访问. 二.方法 #includ ...

  10. 标签中的name属性和ID属性的区别

    标签中的name属性和ID属性的区别 2018年05月13日 10:17:44 tssit 阅读数:760   编程这么久,细想了一下,发现这个问题还不是很清楚,汗!看了几篇文章,整理了一下,分享下! ...