快捷搜索:
来自 计算机编程 2019-08-17 19:45 的文章
当前位置: 67677新澳门手机版 > 计算机编程 > 正文

ORM框架与mysql数据库的无缝过渡

ORM
今昔我们聊聊深刻操作数据库了。
世家都晓得,使用数据库的原生语句来写,一旦数据量了,首先就得疯狂重复写代码,况兼还基本不怎么重用,都以一回写死,后边必要又得再写,那么面临对象编制程序的大旨里面教您三个直面对象数据库,这一年大家看效果
一般说来sql数据库建表一从头那样:

ORM框架与mysql数据库的无缝过渡,orm框架mysql数据库

ORM
方今咱们聊聊深入操作数据库了。
世家都晓得,使用数据库的原生语句来写,一旦数据量了,首先就得疯狂重复写代码,並且还基本不怎么重用,都以贰回写死,后边须求又得再写,那么面临对象编制程序的主导里面教您一个直面临象数据库,这年大家看效果
日常sql数据库建表一开端这么:

1 create table table_name(id int not null auto_increment,
2                         name varchar(32),
3                         password varchar(32),
4                          primary key(id)
5                          )

那是特别简单的sql的表,若是复杂点,加些什么关联的,预计头都要炸,那么,orm是何等鬼?它是贰个框架,封装了数据库原语,大家能够面向对象来嘲讽数据库了。

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy import Colum,Integer,String
from sqlalchemy.orm import sessionmaker

engine=create_engine('mysql pymysql://root:[email protected]/slkdb',encoding ='utf-8',echo=True)
'''
注意写法,orm支持很多借口,我这里是用pymysql,所以是
mysql pymysql://<user>:<password>@<host>/<dbname> #user是用户名,password是密码,host是数据库所在ip地址,dbname是要处理的数据表名字,什么,你的数据表不支持中文?报错?什么拉丁的错?我告诉你,只要在dbname后面加一个?charset=utf8 既可解决

中文支持写法:engine=create_engine('mysql pymysql://root:[email protected]/slkdb?charset=utf8',encoding ='utf-8',echo=True)

由于我是python3,不支持安装MySQL-Python这个模块,这个接口对应的创建就不写了。
'''
Base = declarative_base()#生成orm基类
class User(Base):
    __tablename__='user'#表名
    id = Colum(Integer,primary_key=True)
    name = Colum(String(32))
    password = Colum(String(32))
Base.metadata.create_all(engine)#创建表结构
session_class=sessionmaker(bind=engine)#创建一个数据库的会话,注意这里只是创建了对象
session=session_class()#此时才是生成实例,相当于cursor
User1=User(name='hehe',password = '456456')#生成要生成的数据对象
User2=User(name='zhaff',password = '298789')#生成要生成的数据对象
session.add(User1)
session.add(User2)
session.commit()#此时提交后才最终把数据创建完毕

  

1 create table table_name(id int not null auto_increment,
2                         name varchar(32),
3                         password varchar(32),
4                          primary key(id)
5                          )

好了 数据也插入进去了运维结果消息:

2018-03-06 15:49:45,082 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2018-03-06 15:49:45,082 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,085 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2018-03-06 15:49:45,085 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,085 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
2018-03-06 15:49:45,085 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,086 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2018-03-06 15:49:45,086 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,087 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2018-03-06 15:49:45,087 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,087 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
2018-03-06 15:49:45,087 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,088 INFO sqlalchemy.engine.base.Engine DESCRIBE `user`
2018-03-06 15:49:45,088 INFO sqlalchemy.engine.base.Engine {}
2018-03-06 15:49:45,091 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2018-03-06 15:49:45,092 INFO sqlalchemy.engine.base.Engine INSERT INTO user (name, password) VALUES (%(name)s, %(password)s)
2018-03-06 15:49:45,092 INFO sqlalchemy.engine.base.Engine {'name': 'hehe', 'password': '456456'}
2018-03-06 15:49:45,092 INFO sqlalchemy.engine.base.Engine INSERT INTO user (name, password) VALUES (%(name)s, %(password)s)
2018-03-06 15:49:45,092 INFO sqlalchemy.engine.base.Engine {'name': 'zhaff', 'password': '298789'}
2018-03-06 15:49:45,093 INFO sqlalchemy.engine.base.Engine COMMIT


'''注意:运营进程中或然会出现 Warning: (1366, "Incorrect string value: '\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at row 481")
result = self._query(query)
与此相类似的警戒或许别的巴拉巴拉的警戒,那年不经意它既可,因为她单独是告诫,并非error,程序照旧好端端运行,数据库表内数据已经确立。才具有限,方今并未有缓慢解决那些题材,前期有机缘作者优化'''
世家大概看到这会以为麻蛋怎么更目不暇接了的痛感,究竟那么多包模块的种种乱入还应该有各个对象创立看起来很复杂,

好,是时候上演的确的技术了:

追扩充少已经说过,就地方的add,上边说查询

data = session.query(User).filter(User.id>=1).filter(User.id<4).all()#多规格查询,直接多个filter既可,这里的暗记都是相比较,单等号会出错哟~

print(data)

也足以利用in_([*arg]),表示在arg元组中相配

data = session.query(User).filter(User.name.in_(['zhaoxin','zhaff'])).all()
print(data)

输出:[zhaoxin : 29999, zhaoxin : 29999, zhaff : 298789]

修改:
data = session.query(User).filter(User.name=='hehe').all()[0]#多规格查询,这里的all[0]也能够用frist()替代
print(data)
data.name = 'sb'
session.commit()#修改供给提交,否则不能修改,一般单个修改比较多,多种修改能够用
print(data)

那是特别轻便的sql的表,如若复杂点,加些什么关系的,预计头都要炸,那么,orm是何许鬼?它是二个框架,封装了数据库原语,大家得以面向对象来嘲笑数据库了。

输出结果:

hehe : 456456

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy import Colum,Integer,String
from sqlalchemy.orm import sessionmaker

engine=create_engine('mysql pymysql://root:123456@localhost/slkdb',encoding ='utf-8',echo=True)
'''
注意写法,orm支持很多借口,我这里是用pymysql,所以是
mysql pymysql://<user>:<password>@<host>/<dbname> #user是用户名,password是密码,host是数据库所在ip地址,dbname是要处理的数据表名字,什么,你的数据表不支持中文?报错?什么拉丁的错?我告诉你,只要在dbname后面加一个?charset=utf8 既可解决

中文支持写法:engine=create_engine('mysql pymysql://root:123456@localhost/slkdb?charset=utf8',encoding ='utf-8',echo=True)

由于我是python3,不支持安装MySQL-Python这个模块,这个接口对应的创建就不写了。
'''
Base = declarative_base()#生成orm基类
class User(Base):
    __tablename__='user'#表名
    id = Colum(Integer,primary_key=True)
    name = Colum(String(32))
    password = Colum(String(32))
Base.metadata.create_all(engine)#创建表结构
session_class=sessionmaker(bind=engine)#创建一个数据库的会话,注意这里只是创建了对象
session=session_class()#此时才是生成实例,相当于cursor
User1=User(name='hehe',password = '456456')#生成要生成的数据对象
User2=User(name='zhaff',password = '298789')#生成要生成的数据对象
session.add(User1)
session.add(User2)
session.commit()#此时提交后才最终把数据创建完毕

sb : 456456

同理 删除正是delete了
data = session.query(User).filter(User.name=='sb').all()[0]#多规格查询,这里的all[0]也足以用frist()替代
print(data)
data.name = 'sb'
session.commit()
与上述同类便删除了名叫'sb'的多少。

删改查都以先query查到后才做的修改,那一点并不是弄混了。

分组总结

总计大家都晓得,count,那么这里自然就是

data = session.query(User).filter(User.name=='sb').count()#不曾all,写了all就一定于二个类了,那么此时count就成为了类措施,错误提醒该User类中并未有count那个attribute。

分组计算
from sqlalchemy import func
data = session.query(User.name,func.count(User.name)).group_by(User.name).all()

  

print(data)

输出:[('zhaff', 1), ('zhaoxin', 2)]
group_by的功效就和命令行的group by一样,详细情形移步:

连表查询:

此刻一经成立了三个新的类对象。
class Bala(Base):
*****此地省略了
同上一致

那么多个表,大家要提到他们七个,举个例子表内 name那栏,名字同样的全给自个儿弄出来
result = session.query(User,Bala).filter(User.name == Bala.name).all()#这种是威吓内定name联系的,无需有外键联系
输出结果以列表套元组格式现身,各个元组中对应的正是User.name == Bala.name对应的那两条数据的详细新闻。那就不演示了。
有外键联系的能够应用
result = session.query(User).join(Bala).all()#来实现
下面orm最牛逼的地方正是外键关联的方便性,直接上代码:

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship

engine=create_engine('mysql pymysql://root:[email protected]/slkdb',encoding ='utf-8')
Base = declarative_base()#生成orm基类
class Student(Base):#重新生成两个数据表,之前的都删了重新开始
    __tablename__='student'#表名
    id = Column(Integer,primary_key=True)
    name = Column(String(32),nullable=False)
    register_date = Column(String(32),nullable=False)

    def __repr__(self):
        return 'ID:%s,name: %s'%(self.id,self.name)
class Stu_record(Base):
    __tablename__='stcored'
    id = Column(Integer,primary_key=True)
    day = Column(Integer)
    statue = Column(String(32),nullable=False)
    stu_id = Column(Integer, ForeignKey('student.id'))#外键关联就在这,注意是table_name名.id而不是类对象名.id
    student = relationship('Student',backref='my_study_recode')#这个实现了反向查询,这行代码相当于实例化一个Student的对象实例,此时下面的self.student.name可以调用,通过my_study_recode可以调用Stu_record这个对象的属性,这个函数是从内存中调用,python中封装出来的,并不是数据库里面的功能,如此方便很多倍
    def __repr__(self):
        return '%s第%s天的登录状态%s'%(self.student.name,self.day,self.statue)

Base.metadata.create_all(engine)#创建表结构

session_class=sessionmaker(bind=engine)
session=session_class()
s1 = Student(name='zhaoxin',register_date='2011-02-14')
s2 = Student(name='jianji',register_date='2012-01-14')
s3 = Student(name='ruizi',register_date='2011-05-14')
s4 = Student(name='luoli',register_date='2011-06-11')
t1 = Stu_record(day=1,statue='YES',stu_id=1)
t2 = Stu_record(day=2,statue='NO',stu_id=1)
t3 = Stu_record(day=3,statue='YES',stu_id=1)
t4 = Stu_record(day=4,statue='NO',stu_id=1)
t5 = Stu_record(day=5,statue='YES',stu_id=2)
session.add_all([s1,s2,s3,s4,t1,t2,t3,t4,t5])
session.commit()
s_obj=session.query(Student).filter(Student.name=='zhaoxin').first()#此时返回的是student这个类
print(s_obj.my_study_recode)#通过关联,这个关联是内存里进行的通过类之间的映射,反查到Stu_record中所有的属性,并调用Stu_record的__repr__函数。

  


[zhaoxin第1天的报到状态YES, zhaoxin第2天的报到情形NO, zhaoxin第3天的记名状态YES, zhaoxin第4天的记名情状NO]

一对多外键关联也是如出一辙,可是照旧要留神几个细节:
在关乎时,大家都通晓了是看似那样的stu_id = Column(Integer, ForeignKey('student.id')),那么这么一对多表示着这么的代码不唯有一行,关联的键不平等;
那正是说有几条这么些,就有几条看似student = relationship('Student',backref='my_study_recode')的代码,那个时候要钦赐
foreign_keys = [***此处是本对象下关联外键的属性名***],如此一来Computer就会鉴定分别到底何人关联了哪个人,就不会分不清,如若把那些写进函数,那么Computer就可以搅乱,然后报错:大致说的就是有多个foreign_keys关联在那一个表里,foreign_keys那特性格应该钦定,不然会傻傻分不清楚。

好了,上面最后讲下最重视的多对多关系

平昔在代码里面批注,重新创建新表。(为了演示效果,作者尚未分开放,作为合格的开辟职员,创制和退换查询等文件写在二个代码里实为不妥,不过此间是身体力行,就写一同了。)

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine,Table
from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship

engine=create_engine('mysql pymysql://root:[email protected]/slkdb?charset=utf8')
Base = declarative_base()
book_m2m_author =Table('book_m2m_author',Base.metadata,
                       Column('book_id',Integer,ForeignKey('book.id')),
                       Column('author_id',Integer,ForeignKey('author.id'))
                       )#为什么不用class的方式创建这个表呢?因为我不会在里面插任何数据或者更改,我只需要改源数据就是那两个class里面的,那么这个由映射都会自动更改

class Book(Base):
    __tablename__='book'
    id=Column(Integer,primary_key=True)
    name = Column(String(32))
    put_date = Column(String(32))
    authors = relationship('Author',secondary=book_m2m_author,backref='books')#连接author表,查询时通过第三张表book_m2m_author查询
    def __repr__(self):
        return self.name

class Author(Base):
    __tablename__='author'
    id = Column(Integer, primary_key=True)
    name = name = Column(String(32))
    def __repr__(self):
        return self.name

Base.metadata.create_all(engine)


session_class=sessionmaker(bind=engine)
session=session_class()

b1=Book(name='圣墟 琴帝',put_date='2016-6-12')
b2=Book(name='长生界 我欲封天',put_date='2013-2-19')
b3=Book(name='神墓 求魔',put_date='2009-10-11')
b4=Book(name='仙逆 一念永恒',put_date='2011-6-12')
b5=Book(name='斗罗大陆 遮天',put_date='2010-8-2')
b6=Book(name='三合一',put_date='2018-3-7')

a1=Author(name='辰东')
a2=Author(name='耳根')
a3=Author(name='唐家三少')

b1.authors=[a1,a3]#第三个表通过这个方式关联起author和book这两个表格,以下同。就是Book类中authors里的secondary这个属性的实现。
b2.authors=[a1,a2]
b3.authors=[a1,a2]
b4.authors=[a2,a3]
b5.authors=[a3,a1]
b6.authors=[a1,a2,a3]
session.add_all([b1,b2,b3,b4,b5,b6,a1,a2,a3])
session.commit()

author_obj = session.query(orm_m2m.Author).filter(orm_m2m.Author.name=='辰东').first()
print(author_obj.books)#通过book实现到Book里面调用匹配辰东属性的反查效果
book_obj = session.query(orm_m2m.Book).filter(orm_m2m.Book.name=='三合一').first()
print(book_obj,book_obj.authors)#如此就实现作者查书 和书查作者的关联

  


输出:
[圣墟 琴帝, 长生界 小编欲封天, 神墓 求魔, 斗罗大陆 遮天, 三合一]
三合一 [辰东, 耳根, 唐家三少(táng jiā sān shǎo )]

好了,到此地orm具体也讲完了,实际生活中,多表格关联会众多,借令你看的一脸懵逼,那对不起,恐怕自个儿本身水平还不高,无法疏解入微,人生苦短,作者用python。

 

ORM 未来我们聊聊长远操作数据库了。 我们都晓得,使用数据库的原生语句来写,一旦数...

本文由67677新澳门手机版发布于计算机编程,转载请注明出处:ORM框架与mysql数据库的无缝过渡

关键词: