orm 语法 数据库连接、建表、增删改查、回滚、单键关联 、多键关联、三表关联
1.数据库连接,
#!usr/bin/env/python
# -*- coding:utf-8 -*-
# from wangteng
import sqlalchemy
from sqlalchemy import create_engine, 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://wt:111111@localhost/wt?charset=utf8', echo=True)#跟mysql服务器创建连接
数据库名+模块名://数据库用户名:数据库密码@数据库服务器ip/自己创建的库名(先在库中创建)其中,echo为True代表打开logging。
Base = declarative_base()#生成orm基类
class User(Base): # 定义一个创建表类
__tablename__ = 'user' #表名
id = Column(Integer,primary_key=True) #创建列名 id
name = Column(String(32)) #创建列名 name
password = Column(String(64))#创建列名 password
def __repr__(self):#方便打印
return "%s-%s" % (self.id, self.name)
#创建单外键关联表
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String(32), nullable=False)
user_id = Column(Integer, ForeignKey('user.id')) #创建外键关联
user = relationship("User", backref="addresses") # 这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项
def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address
#创建多外键关联表
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"))
billing_address = relationship("Address1", foreign_keys=[billing_address_id])
shipping_address = relationship("Address1", foreign_keys=[shipping_address_id])
class Address1(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
street = Column(String)
city = Column(String)
state = Column(String)
########################################################################################
Base.metadata.create_all(engine)#创建表结构
Session_class = sessionmaker(bind=engine)#创建与数据库的会话Session_class
session = Session_class() #生成session实例 即cursor
#插入数据
user_obj = Address(email_address=')
session.add(user_obj)
#修改数据
my_user = session.query(User).filter_by(name='wang').first()
my_user.name = "Alex li"
#回滚数据
# session.rollback()#rollback上边的修改将不会生效
session.commit()#注意,除了查询数据,其他都需要session.commit()提交
#查询数据
my_user = session.query(User).filter_by(name='wang').first()#查第一条,.all()查询所有数据,并返回一个列表[1-wang, 2-wang, 3-wang, 4-wang, 5-wang]
print(my_user.name)
#******************关联查询*************************
# 通过user的对象User反查关联的addresses表记录
obj = session.query(User).first()#注意,User是类名,不是表名。通过查询User对象对应的user表,生成一个obj对象,该对象里含有addresses表,通过obj.addresses这种形式可以调用该表
for i in obj.addresses: # 遍历该表,这时,i包含表的各个列名,即:id,email_address,user_id
print('email',i.email_address)
# 通过addresses的对象Address查询关联的user记录
addr_obj = session.query(Address).first()#注意,Address是类名,不是表名。通过查询Address对象对应的addresses表,生成addr_obj对象,该对象里含有user表,通过addr_obj.user调用该表
print(addr_obj.user.name) #name为user表的列名
#********************************************************
#show create table 表名:查看创建表的语句
2.三表关联 多对多关系
自己整理的:
多对多连表操作
需求以及数据库结构
需求:
三张表:
- 主机表:包括nid hostname port ip
- 管理员表:包括:nid username
- 主机对应管理员表: nid 主机id,管理员id
一个管理员帐号(比如root),可以关联多台服务器,一个服务器也可以有多个管理员帐号
先来看下数据结构吧:
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine("mysql+pymysql://root:7ujm8ik,@192.168.4.193:3306/testsql?charset=utf8", max_overflow=5)
Base = declarative_base()
#多对多
class HostToHostUser(Base):
__tablename__ = 'host_to_host_user'
id = Column(Integer, primary_key=True,autoincrement=True)
host_id = Column(Integer,ForeignKey('host.id'))
host_user_id = Column(Integer,ForeignKey('host_user.nid'))
#多对多操作
host = relationship('Host',backref='h')#backref='h'表示host表自动生成某种关联关系,这个关系就成为‘h’关系,只要下边某个表中的backref也指明了这个关系‘h’,那么host表就会与该表形成关联,基于'h'关系,这是道不清理不明的一种关系
host_user = relationship('HostUser',backref='u')#backref='u'表示host_user表自动生成某种关联关系,只要下边某个表中的backref也指明了这个关系‘u‘,那么host_user表就会与该表形成关联,基于'u'关系
class Host(Base):
__tablename__ = 'host'
nid = Column(Integer, primary_key=True,autoincrement=True)
hostname = Column(String(32))
port = Column(String(32))
ip = Column(String(32))
####最简单的方式,添加此行就行:
host_user=relationship('HostUser',secondary=HostToHostUser.__table__,backref='h')#这里backref指明了‘h’关系,那么host表就会与host_user表生成关联关系
#格式:表名(本类是host表,这里写要跟host关联的表)=relationship('对象名(本类是host表,这里写要跟host关联的表的对象名)', secondary=中间表的对象名, backref=关联关系'h')
class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32))
def init_db():
Base.metadata.create_all(engine)
# init_db()
def drop_db():
Base.metadata.drop_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
#======多对多操作
# session.add_all([
# Host(hostname='c1',port='22',ip='1.1.1.1'),
# Host(hostname='c2',port='22',ip='1.1.1.2'),
# Host(hostname='c3',port='22',ip='1.1.1.3'),
# Host(hostname='c4',port='22',ip='1.1.1.4'),
# Host(hostname='c5',port='22',ip='1.1.1.5'),
# ])
# session.commit()
# session.add_all([
# HostUser(username='root'),
# HostUser(username='db'),
# HostUser(username='nb'),
# HostUser(username='sb'),
# ])
# session.commit()
# session.add_all([
# HostToHostUser(host_id=1,host_user_id=1),
# HostToHostUser(host_id=1,host_user_id=2),
# HostToHostUser(host_id=1,host_user_id=3),
# HostToHostUser(host_id=2,host_user_id=2),
# HostToHostUser(host_id=2,host_user_id=4),
# HostToHostUser(host_id=2,host_user_id=3),
# ])
# session.commit()
虚拟关系的查询
需求:查询主机C1的管理员帐号
# 1.反向查找,查询host表中c1的信息,会得到一个对象,对象中存在一个已经设置好的虚拟关系:h
host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
#2.正向查找,遍历对象属性
for item in host_obj.h:
print(item.host_user.username)
结果:
root
db
nb
注意:多对多的话,正反查询都是遍历对象中的属性
同一需求最简单的方式
需求还是同上:查询主机C1的管理员帐号
需要在两张表的一张表中加一条host_user=relationship('HostUser',secondary=HostToHostUser.__table__,backref='h'),我加到了host表中
#最简单的查询方式:
host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
print(host_obj.host_user)
for item in host_obj.host_user:
print(item.username)
结果:
[<__main__.HostUser object at 0x103778710>, <__main__.HostUser object at 0x103778d68>, <__main__.HostUser object at 0x103778e10>]
root
db
nb
alex讲的:
http://blog.csdn.net/Jmilk/article/details/52445093
现在来设计一个能描述“图书”与“作者”的关系的表结构,需求是
- 一本书可以有好几个作者一起出版
- 一个作者可以写好几本书
此时你会发现,用之前学的外键好像没办法实现上面的需求了,因为

当然你更不可以像下面这样干,因为这样就你就相当于有多条书的记录了,太low b了,改书名还得都改。。。

那怎么办呢? 此时,我们可以再搞出一张中间表,就可以了

这样就相当于通过book_m2m_author表完成了book表和author表之前的多对多关联
用orm如何表示呢?
#一本书可以有多个作者,一个作者又可以出版多本书
from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
#创建一个表,将作者表与book表连接起来,该表只有两列,一列是作者id,它的关联外键是作者表的id,另一列是书籍id,它的关联外键是书籍表的id。
book_m2m_author = Table('book_m2m_author', Base.metadata,
Column('book_id',Integer,ForeignKey('books.id')),
Column('author_id',Integer,ForeignKey('authors.id')),
)
class Book(Base):
__tablename__ = 'books'
id = Column(Integer,primary_key=True)
name = Column(String(64))
pub_date = Column(DATE)
authors = relationship('Author',secondary=book_m2m_author,backref='books')#relationship:创建一对多,一本书有多个作者。当我们查询一个Book对象时,该对象的authors属性将返回一个包含若干个author的list。secondary:后跟表名,表示通过中间表book_m2m_author将作者表的对象与书籍表关联起来。格式:‘’关联表的对象名‘’,secondary=中间表的名字,‘表名’
def __repr__(self):
return self.name
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
name = Column(String(32))
def __repr__(self):
return self.name
接下来创建几本书和作者
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Session_class = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例s = Session_class() #生成session实例b1 = Book(name="跟Alex学Python")b2 = Book(name="跟Alex学把妹")b3 = Book(name="跟Alex学装逼")b4 = Book(name="跟Alex学开车")a1 = Author(name="Alex")a2 = Author(name="Jack")a3 = Author(name="Rain")b1.authors = [a1,a2]b2.authors = [a1,a2,a3]s.add_all([b1,b2,b3,b4,a1,a2,a3])s.commit() |
此时,手动连上mysql,分别查看这3张表,你会发现,book_m2m_author中自动创建了多条纪录用来连接book和author表
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
mysql> select * from books;+----+------------------+----------+| id | name | pub_date |+----+------------------+----------+| 1 | 跟Alex学Python | NULL || 2 | 跟Alex学把妹 | NULL || 3 | 跟Alex学装逼 | NULL || 4 | 跟Alex学开车 | NULL |+----+------------------+----------+4 rows in set (0.00 sec)mysql> select * from authors;+----+------+| id | name |+----+------+| 10 | Alex || 11 | Jack || 12 | Rain |+----+------+3 rows in set (0.00 sec)mysql> select * from book_m2m_author;+---------+-----------+| book_id | author_id |+---------+-----------+| 2 | 10 || 2 | 11 || 2 | 12 || 1 | 10 || 1 | 11 |+---------+-----------+5 rows in set (0.00 sec) |
此时,我们去用orm查一下数据
|
1
2
3
4
5
6
7
8
9
|
print('--------通过书表查关联的作者---------')book_obj = s.query(Book).filter_by(name="跟Alex学Python").first()print(book_obj.name, book_obj.authors)print('--------通过作者表查关联的书---------')author_obj =s.query(Author).filter_by(name="Alex").first()print(author_obj.name , author_obj.books)s.commit() |
输出如下
|
1
2
3
4
|
--------通过书表查关联的作者---------跟Alex学Python [Alex, Jack]--------通过作者表查关联的书---------Alex [跟Alex学把妹, 跟Alex学Python] |
牛逼了我的哥!!完善实现多对多
多对多删除
删除数据时不用管boo_m2m_authors , sqlalchemy会自动帮你把对应的数据删除
通过书删除作者
|
1
2
3
4
5
6
|
author_obj =s.query(Author).filter_by(name="Jack").first()book_obj = s.query(Book).filter_by(name="跟Alex学把妹").first()book_obj.authors.remove(author_obj) #从一本书里删除一个作者s.commit() |
直接删除作者
删除作者时,会把这个作者跟所有书的关联关系数据也自动删除
|
1
2
3
4
|
author_obj =s.query(Author).filter_by(name="Alex").first()# print(author_obj.name , author_obj.books)s.delete(author_obj)s.commit() |
6.本节作业
主题:学员管理系统
需求:
- 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下
- 讲师视图
- 管理班级,可创建班级,根据学员qq号把学员加入班级
- 可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的上课纪录, 即每节课都有整班学员上, 为了纪录每位学员的学习成绩,需在创建每节上课纪录是,同时 为这个班的每位学员创建一条上课纪录
- 为学员批改成绩, 一条一条的手动修改成绩
- 学员视图
- 提交作业
- 查看作业成绩
- 一个学员可以同时属于多个班级,就像报了Linux的同时也可以报名Python一样, 所以提交作业时需先选择班级,再选择具体上课的节数
- 附加:学员可以查看自己的班级成绩排名
orm 语法 数据库连接、建表、增删改查、回滚、单键关联 、多键关联、三表关联的更多相关文章
- $Django orm增删改字段、建表 ,单表增删改查,Django请求生命周期
1 orm介绍 ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,“Object Relational Mapping”,即对象-关系映射,简称ORM. 一 ...
- Django框架(八)--单表增删改查,在Python脚本中调用Django环境
一.数据库连接配置 如果连接的是pycharm默认的Sqlite,不用改动,使用默认配置即可 如果连接mysql,需要在配置文件中的setting中进行配置: 将DATABASES={} 更新为 DA ...
- Django框架(九)—— 单表增删改查,在Python脚本中调用Django环境
目录 单表增删改查,在Python脚本中调用Django环境 一.数据库连接配置 二.orm创建表和字段 三.单表增删改查 1.增加数据 2.删除数据 3.修改数据 4.查询数据 四.在Python脚 ...
- GZFramwork数据库层《三》普通主从表增删改查
运行结果: 使用代码生成器(GZCodeGenerate)生成tb_Cusomer和tb_CusomerDetail的Model 生成器源代码下载地址: https://github.com/Gars ...
- GZFramwork数据库层《一》普通表增删改查
运行结果: 使用代码生成器(GZCodeGenerate)生成tb_MyUser的Model 生成器源代码下载地址: https://github.com/GarsonZhang/GZCode ...
- GZFramwork数据库层《四》单据主从表增删改查
同GZFramwork数据库层<三>普通主从表增删改查 不同之处在于:实例 修改为: 直接上效果: 本系列项目源码下载地址:https://github.com/GarsonZhang/G ...
- GZFramwork数据库层《二》单据表增删改查(自动生成单据号码)
运行效果: 使用代码生成器(GZCodeGenerate)生成tb_EmpLeave的Model 生成器源代码下载地址: https://github.com/GarsonZhang/GZCodeGe ...
- Vc数据库编程基础MySql数据库的表增删改查数据
Vc数据库编程基础MySql数据库的表增删改查数据 一丶表操作命令 1.查看表中所有数据 select * from 表名 2.为表中所有的字段添加数据 insert into 表名( 字段1,字段2 ...
- TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查、有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句。
TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查.有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句. select 'grant '|| PRIV ...
- SSH框架下的多表增删改查
下载地址:SSH框架下的多表增删改查 点击进入码云Git下载 点击进入CSDN下载 项目结构: 项目代码就不全部贴出来了,只贴下核心代码.需要项目的自己可以去下载. package com.atgui ...
随机推荐
- C/C++实践笔记 007
进制输出自己写一个_itoa 进制转换void main(){ int num = 0; scanf("%d", &num); printf("num=%i&qu ...
- 音乐播放器 EasyMusic (一)
EasyMusic 一. 代码获取 github 上链接为 https://github.com/VincentWYJ/EasyMusic, 感兴趣的朋友可以同步下来看, 欢迎提出宝贵意见或建议. 1 ...
- 新的一年快开始了,学点新东西吧,从React开始(一)
ReactJS是Facebook出的前端View框架,好东西啊. 看看它的说明: 仅仅是UI 许多人使用React作为MVC架构的V层. 尽管React并没有假设过你的其余技术栈, 但它仍可以作为一个 ...
- javascript 中断函数的使用 setInterval()——返回顶部
方法名称:gotop() 功能描述:点击某个元素,调用方法gotop(),固定间隔,滚动至屏幕顶部 日期 :2016.06.06 16:02 author :cyh2009@live.com < ...
- 泛型-List<T>
声明一个int类型的泛型对象 List<int> list=new List<int>(); list.Add(44);//不用装箱 int i1=list[0];//也不会发 ...
- IOS定位
#import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewCont ...
- Python Day9
Paramiko模块 paramiko模块基于SSH用于连接远程服务器并执行相关操作 基于用户名密码连接: import paramiko # 创建SSH对象 ssh = paramiko.SSHCl ...
- Verilog笔记——YUV2RGB的模块测试
1 YUV2RGB的模块如下: module yuv2rgb( clk, //时钟输入 rstn, //复位输入,低电平复位 y_in, //变换前Y分量输出 cb_in, //变换前Cb分量输出 c ...
- tail -f 和 -F 的用法
tail -f 和 -F 的用法 Tai 2010-08-16 16:03:18 -f 是--follow[=HOW]的缩写, 可以一直读文件末尾的字符并打印出来."[=HOW]" ...
- javaweb学习总结(五)——Servlet开发(一)
一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...