SQLAlchemy 教程 —— 基础入门篇

一、课程简介

1.1 实验内容

本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLAlchemy 进行简单了 CURD 操作及使用 Faker 生成测试数据。

1.2课程知识点

学会用 SQLALchemy 连接数据库(MySQL, SQLite, PostgreSQL), 创建数据表;

掌握表数据之间一对一,一对多及多对多的关系并能转化为对应 SQLAlchemy 描述;

掌握使用 SQLAlchemy 进行 CURD 操作;

学会使用 Faker 生成测试数据

学习本课程需要你对 Python 与 MySQL 都有基本的掌握。

二、ORM 与 SQLAlchemy 简介

ORM 全称 Object Relational Mapping, 翻译过来叫对象关系映射。简单的说,ORM 将数据库中的表与面向对象语言中的类建立了一种对应关系。这样,我们要操作数据库,数据库中的表或者表中的一条记录就可以直接通过操作类或者类实例来完成。

SQLAlchemy 是Python 社区最知名的 ORM 工具之一,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型。

接下来我们将使用 SQLAlchemy 和 MySQL 构建一个博客应用的实验库。

先安装 SQLAlchemy:

$ sudo pip install sqlalchemy

三、连接与创建

实验楼环境已经为我们安装了 MySQL,但还没有启动, 在启动 MySQL 之前,我们需要进行一些配置,将 MySQL 默认的 latin1 编码改成 utf8 。

$ sudo vim /etc/mysql/my.cnf

通过上面的命令打开 MySQL 的配置文件, 添加下面几个配置:

[client]

default-character-set = utf8

[mysqld]

character-set-server = utf8

[mysql]

default-character-set = utf8

保存退出。现在我们可以启动 MySQL 服务了:

$ sudo service mysql start

在命令行下输入下面命令启动 MySQL:

$ mysql -uroot -p

看到上面的内容就说明我们的 MySQL 可以正常启动了(注意,上面的密码不需要输入内容,直接回车就行), 并且我们我们通过命令:

> create database blog;

创建一个名为 blog 的数据库为下面的使用作准备。

另外,我们需要安装一个 Python 与 MySQL 之间的驱动程序:

$ sudo apt-get install python-mysqldb

3.1 连接数据库

我们在 Code 下新建个 Python 文件,叫什么名字就随你便了,这里我们叫 db.py,写入下面的内容:

# coding: utf-8

from sqlalchemy import create_engine

engine = create_engine('mysql+mysqldb://root@localhost:3306/blog')

print(engine)

在上面的程序中,我们连接了默认运行在 3306 端口的 MySQL 中的 blog 数据库。

运行下这个程序,看到下面的信息说明我们已经连接成功了:

3.2 描述表结构

要使用 ORM, 我们需要将数据表的结构用 ORM 的语言描述出来。SQLAlchmey 提供了一套 Declarative 系统来完成这个任务。我们以创建一个 users 表为例,看看它是怎么用 SQLAlchemy 的语言来描述的:

# coding: utf-8

from sqlalchemy import create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import Column, String, Integer

engine = create_engine('mysql+mysqldb://root@localhost:3306/blog?charset=utf8')

Base = declarative_base()

class User(Base):

__tablename__ = 'users'

id = Column(Integer, primary_key=True)

username = Column(String(64), nullable=False, index=True)

password = Column(String(64), nullable=False)

email = Column(String(64), nullable=False, index=True)

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.username)

我们看到,在 User 类中,用 __tablename__ 指定在 MySQL 中表的名字。我们创建了三个基本字段,类中的每一个 Column 代表数据库中的一列,在 Colunm中,指定该列的一些配置。第一个字段代表类的数据类型,上面我们使用 String, Integer 俩个最常用的类型,其他常用的包括:

Text

Boolean

SmallInteger

DateTime

nullable=False 代表这一列不可以为空,index=True 表示在该列创建索引。

另外定义 __repr__ 是为了方便调试,你可以不定义,也可以定义的更详细一些。

$ python db.py

运行程序,我们在 MySQL 中看看表是如何创建的:

四、关系定义

4.1 一对多关系

对于一个普通的博客应用来说,用户和文章显然是一个一对多的关系,一篇文章属于一个用户,一个用户可以写很多篇文章,那么他们之间的关系可以这样定义:

class User(Base):

__tablename__ = 'users'

id = Column(Integer, primary_key=True)

username = Column(String(64), nullable=False, index=True)

password = Column(String(64), nullable=False)

email = Column(String(64), nullable=False, index=True)

articles = relationship('Article')

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.username)

class Article(Base):

__tablename__ = 'articles'

id = Column(Integer, primary_key=True)

title = Column(String(255), nullable=False, index=True)

content = Column(Text)

user_id = Column(Integer, ForeignKey('users.id'))

author = relationship('User')

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.title)

每篇文章有一个外键指向 users 表中的主键 id, 而在 User 中使用 SQLAlchemy 提供的 relationship 描述 关系。而用户与文章的之间的这个关系是双向的,所以我们看到上面的两张表中都定义了 relationship。

SQLAlchemy 提供了 backref 让我们可以只需要定义一个关系:

articles = relationship('Article', backref='author')

添加了这个就可以不用再在 Article 中定义 relationship 了!

4.2 一对一关系

在 User 中我们只定义了几个必须的字段, 但通常用户还有很多其他信息,但这些信息可能不是必须填写的,我们可以把它们放到另一张 UserInfo 表中,这样User 和 UserInfo 就形成了一对一的关系。你可能会奇怪一对一关系为什么不在一对多关系前面?那是因为一对一关系是基于一对多定义的:

class User(Base):

__tablename__ = 'users'

id = Column(Integer, primary_key=True)

username = Column(String(64), nullable=False, index=True)

password = Column(String(64), nullable=False)

email = Column(String(64), nullable=False, index=True)

articles = relationship('Article', backref='author')

userinfo = relationship('UserInfo', backref='user', uselist=False)

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.username)

class UserInfo(Base):

__tablename__ = 'userinfos'

id = Column(Integer, primary_key=True)

name = Column(String(64))

qq = Column(String(11))

phone = Column(String(11))

link = Column(String(64))

user_id = Column(Integer, ForeignKey('users.id'))

定义方法和一对多相同,只是需要添加 userlist=False 。

4.3 多对多关系

一遍博客通常有一个分类,好几个标签。标签与博客之间就是一个多对多的关系。多对多关系不能直接定义,需要分解成俩个一对多的关系,为此,需要一张额外的表来协助完成:

article_tag = Table(

'article_tag', Base.metadata,

Column('article_id', Integer, ForeignKey('articles.id')),

Column('tag_id', Integer, ForeignKey('tags.id'))

)

class Tag(Base):

__tablename__ = 'tags'

id = Column(Integer, primary_key=True)

name = Column(String(64), nullable=False, index=True)

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.name)

4.4 映射到数据

表已经描述好了,在文件末尾使用下面的命令在我们连接的数据库中创建对应的表:

if __name__ == '__main__':

Base.metadata.create_all(engine)

进入 MySQL 看看:

所有的表都已经创建好了!

五、简单 CURD

当你想打电话给朋友时,你是否得用手机拨通他的号码才能建立起一个会话?同样的,你想和 MySQL 交谈也得先通过 SQLAlchemy 建立一个会话:

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)

session = Session()

你可以把 sessionmaker 想象成一个手机,engine 当做 MySQL 的号码,拨通这个“号码”我们就创建了一个 Session 类,下面就可以通过这个类的实例与 MySQL 愉快的交谈了!

5.1 Create

如果你玩过LOL, 我想你一定知道Faker。而在 Python的世界中,Faker 是用来生成虚假数据的库。 安装它:

$ sudo pip install faker

下面结合 Faker 库创建一些测试数据:

faker = Factory.create()

Session = sessionmaker(bind=engine)

session = Session()

faker_users = [User(

username=faker.name(),

password=faker.word(),

email=faker.email(),

) for i in range(10)]

session.add_all(faker_users)

faker_categories = [Category(name=faker.word()) for i in range(5)]

session.add_all(faker_categories)

faker_tags= [Tag(name=faker.word()) for i in range(20)]

session.add_all(faker_tags)

for i in range(100):

article = Article(

title=faker.sentence(),

content=' '.join(faker.sentences(nb=random.randint(10, 20))),

author=random.choice(faker_users),

category=random.choice(faker_categories)

)

for tag in random.sample(faker_tags, random.randint(2, 5)):

article.tags.append(tag)

session.add(article)

session.commit()

在上面的代码中我们创建了10个用户,5个分类,20个标签,100篇文章,并且为每篇文章随机选择了2~5个标签。

使用 SQLAlchemy 往数据库中添加数据,我们只需要创建相关类的实例,调用 session.add() 添加一个,或者 session.add_all() 一次添加多个, 最后 session.commit() 就可以了。

5.2 Retrieve

如果我们知道用户 id,就可以用 get 方法, filter_by 用于按某一个字段过滤,而 filter 可以让我们按多个字段过滤,all 则是获取所有。

获取某一字段值可以直接类的属性获取:

5.3 Update

更新一个字段:

>>> a = session.query(Article).get(10)

>>> a.title = 'My test blog post'

>>> session.add(a)

>>> session.commit()

添加一个标签:

>>> a = session.query(Article).get(10)

>>> a.tags.append(Tag(name='python'))

>>> session.add(a)

>>> session.commit()

5.4 Delete

>>> a = session.query(Article).get(10)

>>> session.delete(a)

>>> session.commit()

删除直接调用 delete 删除获取到的对象,提交 session 即可。

完整代码

# coding: utf-8

import random

from faker import Factory

from sqlalchemy import create_engine, Table

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import ForeignKey

from sqlalchemy import Column, String, Integer, Text

from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine('mysql+mysqldb://root@localhost:3306/blog?charset=utf8')

Base = declarative_base()

class User(Base):

__tablename__ = 'users'

id = Column(Integer, primary_key=True)

username = Column(String(64), nullable=False, index=True)

password = Column(String(64), nullable=False)

email = Column(String(64), nullable=False, index=True)

articles = relationship('Article', backref='author')

userinfo = relationship('UserInfo', backref='user', uselist=False)

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.username)

class UserInfo(Base):

__tablename__ = 'userinfos'

id = Column(Integer, primary_key=True)

name = Column(String(64))

qq = Column(String(11))

phone = Column(String(11))

link = Column(String(64))

user_id = Column(Integer, ForeignKey('users.id'))

class Article(Base):

__tablename__ = 'articles'

id = Column(Integer, primary_key=True)

title = Column(String(255), nullable=False, index=True)

content = Column(Text)

user_id = Column(Integer, ForeignKey('users.id'))

cate_id = Column(Integer, ForeignKey('categories.id'))

tags = relationship('Tag', secondary='article_tag', backref='articles')

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.title)

class Category(Base):

__tablename__ = 'categories'

id = Column(Integer, primary_key=True)

name = Column(String(64), nullable=False, index=True)

articles = relationship('Article', backref='category')

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.name)

article_tag = Table(

'article_tag', Base.metadata,

Column('article_id', Integer, ForeignKey('articles.id')),

Column('tag_id', Integer, ForeignKey('tags.id'))

)

class Tag(Base):

__tablename__ = 'tags'

id = Column(Integer, primary_key=True)

name = Column(String(64), nullable=False, index=True)

def __repr__(self):

return '%s(%r)' % (self.__class__.__name__, self.name)

if __name__ == '__main__':

Base.metadata.create_all(engine)

faker = Factory.create()

Session = sessionmaker(bind=engine)

session = Session()

faker_users = [User(

username=faker.name(),

password=faker.word(),

email=faker.email(),

) for i in range(10)]

session.add_all(faker_users)

faker_categories = [Category(name=faker.word()) for i in range(5)]

session.add_all(faker_categories)

faker_tags= [Tag(name=faker.word()) for i in range(20)]

session.add_all(faker_tags)

for i in range(100):

article = Article(

title=faker.sentence(),

content=' '.join(faker.sentences(nb=random.randint(10, 20))),

author=random.choice(faker_users),

category=random.choice(faker_categories)

)

for tag in random.sample(faker_tags, random.randint(2, 5)):

article.tags.append(tag)

session.add(article)

session.commit()

六、总结与习题

本篇教程带领大家使用 SQLAlchemy 创建了一个博客应用的数据库及相关表,再次过程中, 介绍了使用 SQLAlchemy 定义一对一、一对多及多对多关系,CURD 及使用 Faker 生成测试数据。

习题

现在博客应用需要添加评论功能,使用 SQLAlchemy 创建一张评论表, 并使用 Faker 为每篇文章生成几条测试评论。

sqlalchemy mysql教程_SQLAlchemy 教程 —— 基础入门篇相关推荐

  1. php教程目录,php基础入门篇-文件和目录操作_PHP教程

    一篇关于php 入门的朋友参考的关于文件和目录的各种操作函数与实例应用,有需要的朋友可以简单的参考一下. 本章可以算是上一章的延续,介绍了除文件实际内容之外的附加信息,包括文件的大小.目录.访问权限等 ...

  2. linux入门_Linux超详细0基础入门篇(一)

    首先要感谢大康老师对我在Linux操作系统上的教导. 今天来讲一下用途广泛的Linux的基础入门教程 仅仅是做入门使用,如果想更加深入的学习那就需要自己做探索了. 本次例子使用的是kali linux ...

  3. EGE基础入门篇(二):开始使用EGE

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(一):绘图基础知识 下一篇:EGE基础入门篇(三):开场动画 EGE基础入门篇(二) 文章最后修改时间:2021年6月23日19:30:47 文章目录 ...

  4. XSS注入基础入门篇

    XSS注入基础入门篇 1.XSS基础概念 2. XSS的分类以及示例 2.1 反射型XSS 2.1.1 示例1:dvwa low 级别的反射型XSS 2.1.2 攻击流程 2.2 DOM型XSS 2. ...

  5. 经典再现,看到就是赚到。尚硅谷雷神 - SpringBoot 2.x 学习笔记 - 基础入门篇

    SpringBoot 2.x 时代 – 基础入门篇 视频学习地址:https://www.bilibili.com/video/BV1Et411Y7tQ?p=112&spm_id_from=p ...

  6. 《Ansible权威指南 》一 第一篇 Part 1 基础入门篇

    本节书摘来自华章出版社<Ansible权威指南 >一书中的第1章,第1.1节,李松涛 魏 巍 甘 捷 著更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 ...

  7. 云小课|DGC数据开发之基础入门篇

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:欢迎来到DGC数据 ...

  8. FPGA基础入门篇(四) 边沿检测电路

    FPGA基础入门篇(四)--边沿检测电路 一.边沿检测 边沿检测,就是检测输入信号,或者FPGA内部逻辑信号的跳变,即上升沿或者下降沿的检测.在检测到所需要的边沿后产生一个高电平的脉冲.这在FPGA电 ...

  9. JAVA中整型常量的长度,Java基础入门篇(三)——Java常量、变量,

    Java基础入门篇(三)--Java常量.变量, 一.Java常量 (一)什么是常量 常量指的是在程序中固定不变的值,是不能改变的数据.在Java中,常量包括整型常量.浮点型常量.布尔常量.字符常量等 ...

最新文章

  1. 自然语言处理:汉语分词
  2. 如何在Python上用jieba库分析TXT文件的词频
  3. java 怎么判别注释符_java学习笔记二(注释、关键字、标识符)
  4. Hadoop的TextInputFormat的作用,如何自定义实现的
  5. 淘宝成全球电商第一人气网站
  6. 上传docker镜像到hub.docker
  7. 获取手机IMEI和UID
  8. 面试题_翻转句子中单词的顺序
  9. 洛谷 P4099 SAO —— 树形dp
  10. 虚拟机安装linux输入密钥,远程连接虚拟机并做密钥认证
  11. Android手机端脚本录制
  12. 11、C++各大有名库的介绍——综合
  13. 负折射率波导matlab,介质波导的数值模拟
  14. python使用 Captcha 模块来生成验证码图片
  15. Nature Neuroscience:怀孕导致人类大脑结构的长久改变
  16. 高校数据中心有哪些特点,目前主要存在哪些问题?
  17. 前端怎么画三角形_css画出三角形和梯形
  18. 【opencv】【python】libpng warning: iCCP: known incorrect sRGB profile 解决
  19. 前端下载图片的N种方法
  20. html中常见表达颜色的三种方式

热门文章

  1. 关于php使用fputcsv进行大数据的导出
  2. 人生轻似梦,芳华淡随风(转)
  3. mysql从库数据源_SoapUI Pro教程:如何使用MySQL服务器作为数据源-从MySQL数据库获取数据...
  4. 计算机毕业设计中ASP.NET数据源控件
  5. jsp页面 字体颜色 白色_电商美工不会优化页面?试试这6招
  6. html5+桌面推送,HTML5 Web Notifications 桌面推送小记
  7. 什么是提花?大提花面料与小提花面料如何区别?
  8. QSerialport多线程方法
  9. 光源选型的要素有哪些?
  10. 面向对象程序设计概述(金老师第一讲)