orm 语法 数据库连接、建表、增删改查、回滚、单键关联 、多键关联、三表关联...

1.数据库连接,

 1 #!usr/bin/env/python
 2 # -*- coding:utf-8 -*-
 3 # from  wangteng
 4 import sqlalchemy
 5 from sqlalchemy import create_engine, ForeignKey
 6 from sqlalchemy.ext.declarative import declarative_base
 7 from sqlalchemy import Column,Integer,String
 8 from sqlalchemy.orm import sessionmaker, relationship
 9 
10 engine = create_engine('mysql+pymysql://wt:111111@localhost/wt?charset=utf8', echo=True)#跟mysql服务器创建连接
数据库名+模块名://数据库用户名:数据库密码@数据库服务器ip/自己创建的库名(先在库中创建)其中,echoTrue代表打开logging。
11 Base = declarative_base()#生成orm基类 12 13 14 class User(Base): # 定义一个创建表类 15 __tablename__ = 'user' #表名 16 id = Column(Integer,primary_key=True) #创建列名 id 17 name = Column(String(32)) #创建列名 name 18 password = Column(String(64))#创建列名 password 19 20 def __repr__(self):#方便打印 21 return "%s-%s" % (self.id, self.name) 22 23 #创建单外键关联表 24 class Address(Base): 25 __tablename__ = 'addresses' 26 id = Column(Integer, primary_key=True) 27 email_address = Column(String(32), nullable=False) 28 user_id = Column(Integer, ForeignKey('user.id')) #创建外键关联 29 user = relationship("User", backref="addresses") # 这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项 30 31 def __repr__(self): 32 return "<Address(email_address='%s')>" % self.email_address 33 34 #创建多外键关联表 35 class Customer(Base): 36 __tablename__ = 'customer' 37 id = Column(Integer, primary_key=True) 38 name = Column(String) 39 40 billing_address_id = Column(Integer, ForeignKey("address.id"))#两个关联外键 41 shipping_address_id = Column(Integer, ForeignKey("address.id")) 42 43 billing_address = relationship("Address1", foreign_keys=[billing_address_id]) 44 shipping_address = relationship("Address1", foreign_keys=[shipping_address_id]) 45 46 47 class Address1(Base): 48 __tablename__ = 'address' 49 id = Column(Integer, primary_key=True) 50 street = Column(String) 51 city = Column(String) 52 state = Column(String) 53 ######################################################################################## 54 Base.metadata.create_all(engine)#创建表结构 55 56 Session_class = sessionmaker(bind=engine)#创建与数据库的会话Session_class 57 session = Session_class() #生成session实例 即cursor 58 #插入数据 59 user_obj = Address(email_address='11.com', user_id='1') 60 session.add(user_obj) 61 #修改数据 62 my_user = session.query(User).filter_by(name='wang').first() 63 my_user.name = "Alex li" 64 #回滚数据 65 # session.rollback()#rollback上边的修改将不会生效 66 67 session.commit()#注意,除了查询数据,其他都需要session.commit()提交 68 #查询数据 69 my_user = session.query(User).filter_by(name='wang').first()#查第一条,.all()查询所有数据,并返回一个列表[1-wang, 2-wang, 3-wang, 4-wang, 5-wang] 70 print(my_user.name) 71 #******************关联查询************************* 72 # 通过user的对象User反查关联的addresses表记录 73 obj = session.query(User).first()#注意,User是类名,不是表名。通过查询User对象对应的user表,生成一个obj对象,该对象里含有addresses表,通过obj.addresses这种形式可以调用该表 74 for i in obj.addresses: # 遍历该表,这时,i包含表的各个列名,即:id,email_address,user_id 75 print('email',i.email_address) 76 # 通过addresses的对象Address查询关联的user记录 77 addr_obj = session.query(Address).first()#注意,Address是类名,不是表名。通过查询Address对象对应的addresses表,生成addr_obj对象,该对象里含有user表,通过addr_obj.user调用该表 78 print(addr_obj.user.name) #name为user表的列名 79 #******************************************************** 80 #show create table 表名:查看创建表的语句

2.三表关联   多对多关系

自己整理的:

多对多连表操作

需求以及数据库结构

需求:

三张表:

  1. 主机表:包括nid hostname port ip
  2. 管理员表:包括:nid username
  3. 主机对应管理员表: 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

现在来设计一个能描述“图书”与“作者”的关系的表结构,需求是

  1. 一本书可以有好几个作者一起出版
  2. 一个作者可以写好几本书

此时你会发现,用之前学的外键好像没办法实现上面的需求了,因为

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

 

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

这样就相当于通过book_m2m_author表完成了book表和author表之前的多对多关联

用orm如何表示呢?

 1 #一本书可以有多个作者,一个作者又可以出版多本书
 2 
 3 
 4 from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
 5 from sqlalchemy.orm import relationship
 6 from sqlalchemy.ext.declarative import declarative_base
 7 from sqlalchemy import create_engine
 8 from sqlalchemy.orm import sessionmaker
 9 
10 
11 Base = declarative_base()
12 #创建一个表,将作者表与book表连接起来,该表只有两列,一列是作者id,它的关联外键是作者表的id,另一列是书籍id,它的关联外键是书籍表的id。
13 book_m2m_author = Table('book_m2m_author', Base.metadata,
14                         Column('book_id',Integer,ForeignKey('books.id')),
15                         Column('author_id',Integer,ForeignKey('authors.id')),
16                         )
17 
18 class Book(Base):
19     __tablename__ = 'books'
20     id = Column(Integer,primary_key=True)
21     name = Column(String(64))
22     pub_date = Column(DATE)
23     authors = relationship('Author',secondary=book_m2m_author,backref='books')#relationship:创建一对多,一本书有多个作者。当我们查询一个Book对象时,该对象的authors属性将返回一个包含若干个author的list。secondary:后跟表名,表示通过中间表book_m2m_author将作者表的对象与书籍表关联起来。格式:‘’关联表的对象名‘’,secondary=中间表的名字,‘表名’
24 
25     def __repr__(self):
26         return self.name
27 
28 class Author(Base):
29     __tablename__ = 'authors'
30     id = Column(Integer, primary_key=True)
31     name = Column(String(32))
32 
33     def __repr__(self):
34         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,不是实例
=  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.本节作业

主题:学员管理系统

需求:

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

 

转载于:https://www.cnblogs.com/wt11/p/5993476.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值