SQLAlchemy介绍和基本使用
pymysql
:pymysql
是用Python
来操作mysql
的包,因此通过pip
来安装,命令如下:pip3 install pymysql
。如果您用的是Python 3
,请安装pymysql
豆瓣源 pip install pymysql -i https://pypi.douban.com/simple
SQLAlchemy
:SQLAlchemy
是一个数据库的ORM
框架,我们在后面会用到。安装命令为:pip3 install SQLAlchemy
。
豆瓣源 pip install sqlalchemy -i https://pypi.douban.com/simple
#encoding:utf-8
# __author__ = 'donghao'
# __time__ = 2019/1/4 17:07
from sqlalchemy import create_engine
#数据库配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'firstsqlalchemy'
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = "mysql+pymysql://{}:{}@{}/{}".format(USERNAME,PASSWORD,HOSTNAME,DATABASE)
# 创建引擎
engine = create_engine(DB_URL,encoding='utf8')
#创建连接
with engine.connect() as con:
rs = con.execute('SELECT 1')
print rs.fetchone()
首先从sqlalchemy
中导入create_engine
,用这个函数来创建引擎,然后用engine.connect()
来连接数据库。其中一个比较重要的一点是,通过create_engine
函数的时候,需要传递一个满足某种格式的字符串,对这个字符串的格式来进行解释:
dialect+driver://username:password@host:port/database?charset=utf8
dialect
是数据库的实现,比如MySQL
、PostgreSQL
、SQLite
,并且转换成小写。driver
是Python
对应的驱动,如果不指定,会选择默认的驱动,比如MySQL的默认驱动是MySQLdb
。username
是连接数据库的用户名,password
是连接数据库的密码,host
是连接数据库的域名,port
是数据库监听的端口号,database
是连接哪个数据库的名字。
如果以上输出了1
,说明SQLAlchemy
能成功连接到数据库。
用SQLAlchemy执行原生SQL:
我们将上一个例子中的数据库配置选项单独放在一个constants.py
的文件中,看以下例子:
from sqlalchemy import create_engine
from constants import DB_URI
#连接数据库
engine = create_engine(DB_URI,echo=True)
# 使用with语句连接数据库,如果发生异常会被捕获
with engine.connect() as con:
# 先删除users表
con.execute('drop table if exists authors')
# 创建一个users表,有自增长的id和name
con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
# 插入两条数据到表中
con.execute('insert into persons(name) values("abc")')
con.execute('insert into persons(name) values("xiaotuo")')
# 执行查询操作
results = con.execute('select * from persons')
# 从查找的结果中遍历
for result in results:
print(result)
SQLAlchemy
使用SQLAlchemy:
要使用ORM
来操作数据库,首先需要创建一个类来与对应的表进行映射
from sqlalchemy import Column,Integer,String
from constants import DB_URI
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine(DB_URI,echo=True)
# 所有的类都要继承自`declarative_base`这个函数生成的基类
Base = declarative_base(engine)
class User(Base):
# 定义表名为users
__tablename__ = 'users'
# 将id设置为主键,并且默认是自增长的
id = Column(Integer,primary_key=True)
# name字段,字符类型,最大的长度是50个字符
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 让打印出来的数据更好看,可选的
def __repr__(self):
return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % (self.id,self.name,self.fullname,self.password
SQLAlchemy
会自动的设置第一个Integer
的主键并且没有被标记为外键的字段添加自增长的属性。因此以上例子中id
自动的变成自增长的。以上创建完和表映射的类后,还没有真正的映射到数据库当中,执行以下代码将类映射到数据库中:
Base.metadata.create_all()
增删改查
增:
# 1.增加
def add_func():
p = Person(username='donghao')
session.add(p)
session.commit()
查:
def check():
Persons = session.query(Person).all()
for person in Persons:
print(person.username)
删:
def delete():
Persons = session.query(Person).first()
session.delete(Persons)
session.commit()
改:
def edit():
Persons = session.query(Person).first()
Persons.username = '123
SQLAlchemy的ORM(2)
Column常用参数:
default
:默认值。nullable
:是否可空。primary_key
:是否为主键。unique
:是否唯一。autoincrement
:是否自动增长。onupdate
:更新的时候执行的函数。name
:该属性在数据库中的字段映射。
sqlalchemy常用数据类型:
Integer
:整形。Float
:浮点类型。Boolean
:传递True/False
进去。DECIMAL
:定点类型。enum
:枚举类型。Date
:传递datetime.date()
进去。DateTime
:传递datetime.datetime()
进去。Time
:传递datetime.time()
进去。String
:字符类型,使用时需要指定长度,区别于Text
类型。Text
:文本类型。LONGTEXT
:长文本类型。
query可用参数:
- 模型对象。指定查找这个模型中所有的对象。
- 模型中的属性。可以指定只查找某个模型的其中几个属性。
- 聚合函数。
func.count
:统计行的数量。func.avg
:求平均值。func.max
:求最大值。func.min
:求最小值。func.sum
:求和。
过滤条件:
过滤是数据提取的一个很重要的功能,以下对一些常用的过滤条件进行解释,并且这些过滤条件都是只能通过filter
方法实现的:
equals
:query.filter(User.name == 'ed')
not equals
:query.filter(User.name != 'ed')
like
:query.filter(User.name.like('%ed%'))
in
:query.filter(User.name.in_(['ed','wendy','jack']))
# 同时,in也可以作用于一个Query
query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%ed%'))))
not in
:query.filter(~User.name.in_(['ed','wendy','jack']))
is null
:query.filter(User.name==None)
# 或者是
query.filter(User.name.is_(None))
is not null
:query.filter(User.name != None)
# 或者是
query.filter(User.name.isnot(None))
and
:from sqlalchemy import and_
query.filter(and_(User.name=='ed',User.fullname=='Ed Jones'))
# 或者是传递多个参数
query.filter(User.name=='ed',User.fullname=='Ed Jones')
# 或者是通过多次filter操作
query.filter(User.name=='ed').filter(User.fullname=='Ed Jones')
or
:from sqlalchemy import or_ query.filter(or_(User.name=='ed',User.name=='wendy'))
SQLAlchemy的ORM(3)
查找方法:
介绍完过滤条件后,有一些经常用到的查找数据的方法也需要解释一下:
all()
:返回一个Python
列表(list
):query = session.query(User).filter(User.name.like('%ed%').order_by(User.id)
# 输出query的类型
print type(query)
> <type 'list'>
# 调用all方法
query = query.all()
# 输出query的类型
print type(query)
> <class 'sqlalchemy.orm.query.Query'>
first()
:返回Query
中的第一个值:user = session.query(User).first()
print user
> <User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
one()
:查找所有行作为一个结果集,如果结果集中只有一条数据,则会把这条数据提取出来,如果这个结果集少于或者多于一条数据,则会抛出异常。总结一句话:有且只有一条数据的时候才会正常的返回,否则抛出异常:# 多于一条数据
user = query.one()
> Traceback (most recent call last):
> ...
> MultipleResultsFound: Multiple rows were found for one()
# 少于一条数据
user = query.filter(User.id == 99).one()
> Traceback (most recent call last):
> ...
> NoResultFound: No row was found for one()
# 只有一条数据
> query(User).filter_by(name='ed').one()
one_or_none()
:跟one()
方法类似,但是在结果集中没有数据的时候也不会抛出异常。scalar()
:底层调用one()
方法,并且如果one()
方法没有抛出异常,会返回查询到的第一列的数据:session.query(User.name,User.fullname).filter_by(name='ed').scalar()
文本SQL:
SQLAlchemy
还提供了使用文本SQL的方式来进行查询,这种方式更加的灵活。而文本SQL要装在一个text()
方法中,看以下例子:
from sqlalchemy import text
for user in session.query(User).filter(text("id<244")).order_by(text("id")).all():
print user.name
如果过滤条件比如上例中的244存储在变量中,这时候就可以通过传递参数的形式进行构造:
session.query(User).filter(text("id<:value and name=:name")).params(value=224,name='ed').order_by(User.id)
在文本SQL中的变量前面使用了:
来区分,然后使用params
方法,指定需要传入进去的参数。另外,使用from_statement
方法可以把过滤的函数和条件函数都给去掉,使用纯文本的SQL:
sesseion.query(User).from_statement(text("select * from users where name=:name")).params(name='ed').all()
使用from_statement
方法一定要注意,from_statement
返回的是一个text
里面的查询语句,一定要记得调用all()
方法来获取所有的值。
计数(Count):
Query
对象有一个非常方便的方法来计算里面装了多少数据:
session.query(User).filter(User.name.like('%ed%')).count()
当然,有时候你想明确的计数,比如要统计users
表中有多少个不同的姓名,那么简单粗暴的采用以上count
是不行的,因为姓名有可能会重复,但是处于两条不同的数据上,如果在原生数据库中,可以使用distinct
关键字,那么在SQLAlchemy
中,可以通过func.count()
方法来实现:
from sqlalchemy import func
session.query(func.count(User.name),User.name).group_by(User.name).all()
# 输出的结果
> [(1, u'ed'), (1, u'fred'), (1, u'mary'), (1, u'wendy')]
另外,如果想实现select count(*) from users
,可以通过以下方式来实现:
session.query(func.count(*)).select_from(User).scalar()
当然,如果指定了要查找的表的字段,可以省略select_from()
方法:
session.query(func.count(User.id)).scalar()
SQLAlchemy介绍和基本使用的更多相关文章
- SQLAlchemy介绍
SQLAlchemy 增删改查 一对多 多对多 Python 的 ORM 框架 SQLAlchemy 有些同学已经听说过这个框架的大名了,也听说了 SQLAlchemy 没有 Django 的 M ...
- sqlalchemy模块介绍、单表操作、一对多表操作、多对多表操作、flask集成.
今日内容概要 sqlalchemy介绍和快速使用 单表操作增删查改 一对多 多对多 flask集成 内容详细 1.sqlalchemy介绍和快速使用 # SQLAlchemy是一个基于 Python实 ...
- SQLAlchemy表操作和增删改查
一.SQLAlchemy介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数 ...
- python 全栈开发,Day141(flask之应用上下文,SQLAlchemy)
一.flask之应用上下文 由于时间关系,详细过程略... 草稿图 参考链接: http://www.cnblogs.com/zhaopanpan/p/9457343.html 总结: 上下文管理(应 ...
- Python中操作SQLAlchemy
一.ORM 框架简介 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应用开发环境中的主流开发方法 ...
- python3之SQLAlchemy
1.SQLAlchemy介绍 SQLAlchemy是Python SQL工具包和对象关系映射器,为应用程序开发人员提供了SQL的全部功能和灵活性. 它提供了一整套众所周知的企业级持久性模式,专为高效和 ...
- SQLAlchemy基本使用(Flask中)
SQLAlchemy介绍 SQLAlchemy是一个基于Python实现的ORM框架. 该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据 ...
- SQLAlchemy(3)
一. SQLAlchemy 介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使 ...
- SQLAlchemy技术手册
一.ORM 框架简介 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应用开发环境中的主流开发方法 ...
随机推荐
- java正则表达式笔记
import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntax ...
- android OkHttpUtils 使用JSON数据作为请求参数
如果就直接将JSON作为请求字符串,服务端会出现中文乱码.所以只需要将请求的整个JSON参数字符串编码一次,然后服务端解码一次.我这里服务端使用的servlet,下面会两段代码贴出. android: ...
- 实现一套山寨springMVC
重复造轮子没有意义,但是通过现已存在的轮子,模仿着思路去实现一套,还是比较cool的.花了三天,终于深夜搞定!收益都在代码里,我干了,您随意! 一.简单思路 简单介绍: 1.所有的请求交给TyDisp ...
- Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)
https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...
- c#文件比较Code
我想我们很多时候想比较一个文件里面是否有改动,比如一个dll库是新加了一个方法或修改了其中的方法实现,不能通过可视化的工具来比较的时候,可以用这个小工具来比较, 以下是比较文件的代码. using S ...
- asp.net 重写URL方法和封装好的DLL
.net 重写URL方法和封装好的DLL URL重写方法DLL(2.0)
- html部分常用标签的含义及作用
1.a 超链接 <a> 标签定义超链接,用于从一张页面链接到另一张页面.<a> 标签中必须提供 href 属性或 name 属性,它指示链接的目标. 例如:点击 百度一下 跳转 ...
- JS中访问对象的两种方式区别
可以使用下面两种方式访问对象的属性和方法 1.对象名.属性名 对象名.方法名() 2.对象名["属性名"] 对象名["方法名"]() var obj = { n ...
- ubuntu apache linux
在ubuntu下安装的apache, 很多配置文件都分开写了,需要了解一下各部分: http://blog.csdn.net/veizz/article/details/7410784 Ubuntu下 ...
- php apache
php与Apache配置基础知识 1.在 AllowOverride 设置为 None 时,.htaccess 文件将被完全忽略.当此指令设置为All时,所有具有“.htaccess” 作用域的指令都 ...