最近看项目,又是sqlalchemy,又有flask_sqlalchemy,两者的一些用法差点搞混了。这里总结一下。


一、SQL Alchemy

SQL Alchemy是python中最著名的ORM(Object Relationship Mapping)框架。ORM:对象关系映射。即将用户定义的Python类与数据库表相关联,并将这些类(对象)的实例与其对应表中的行相关联。


1. SQL Alchemy 基本操作

1.1 连接数据库

from sqlalchemy import create_engine

# 创建数据库引擎
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/my_db?charset=utf8mb4")

create_engine()函数中的字符串的意义是,数据库+数据库连接框架://用户名:密码@IP地址:端口号/数据库名称?连接参数。

解释:

连接mysql数据库,采用的pymysql框架连接(当然还有其他的连接框架),登陆数据库的用户和密码是root和123456,mysql数据库系统地址时127.0.0.1:3306,连接的具体数据库是my_db,并设置了字符编码是utf8mb4。

1.2 声明映射(建立数据库表的模型)

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String # 声明性基类
Base = declarative_base() # 构建数据库表的模型类
class User(Base):
__tablename__ = 'users' id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String) # 这个是可选的方法,这里自定义在显示User对象时的格式
def __repr__(self):
return "<User(name='%s', fullname='%s', nickname='%s')>" % (
self.name, self.fullname, self.nickname)

解释:

使用Declarative系统映射的类是根据基类定义的,该基类维护相对于该基类的类和表的目录 - 这称为声明性基类。我们的应用程序通常在一个常用的模块中只有一个这个基础的实例。我们使用declarative_base() 函数创建基类。

__tablename__变量声明了在根据这个类创建表时表的名字。

现在我们有了一个类“Base”,我们可以根据它定义任意数量的映射类。上面我们根据它定义了一个users表,表中含有字段id、name、fullname

1.3 创建映射类的实例


user1 = User(name='ed', fullname='Ed Jones')
user2 = User(name='ed2', fullname='Ed2 Jones2')

1.4 创建会话

上面我们创建了连接数据库的引擎,这里需要引擎来创建一个session,后面才能通过session与数据库进行交互。


Session = sessionmaker(engine)
db_session = Session()

1.5 单表的增删改查

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from Model import User # 通常我们把数据库表模型统一放到一个模块里,所以这里需要导入 # 准备工作
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8mb4") Session = sessionmaker(engine)
db_session = Session() # 1. 增加数据add(创建表结构的类名(字段名=添加的数据))
db_session.add(User(name="ZWQ", fullname="ZWQ zzzzz")) # 相当于建立一条添加数据的sql语句
db_session.commit() # 执行 # 批量添加
user1 = User(name='ed', fullname='Ed Jones')
user2 = User(name='ed2', fullname='Ed2 Jones2')
db_session.add_all([user1, user2])
db_session.commit() # 2.查询 query(表结构的类名)
res = db_session.query(User)
print(res) # 直接翻译输出对应的SQL查询语句 res = db_session.query(User).all() # 返回表中所有数据对象
print(res) for u in res:
print(u.id, u.name, u.fullname) res = db_session.query(Users).first() # 取第一个,返回是对象
print(res.id, res.name) res = db_session.query(User).filter(Users.id == 3).first() # 返回符合条件查询结果
print(res.name) res = db_session.query(User).filter(User.id <= 2, User.name == "ZWQ").all() # filter中的条件可以是模糊条件,多个条件
for u in res:
print(u.id,u.name) # 3.更改数据 update({k:v})
res = db_session.query(Users).filter(Users.id == 1).update({"name":"DragonFire"})
print(res)
db_session.commit() res = db_session.query(User).update({"name":"ZWQ"}) # 全部修改,返回修改的数据个数
print(res)
db_session.commit() # 4.删除 delete()结合查询条件删除
res = db_session.query(User).filter(User.id == 1).delete() # 删除否合条件的数据,返回删除数量
print(res)
db_session.commit() res = db_session.query(User).delete() # 删除表中所有数据,返回删除数量
print(res)
db_session.commit() # 关闭session
db_session.close()

回滚:如果我们通过db_session.add()不小心把错误的信息添加进去了,可以使用de_session.rollback()回滚操作。

2. SQL Alchemy之(一对多)(多对多)

参考文章:

https://blog.csdn.net/tianpingxian/article/details/82720442

看见了一片不错的文章,就不自己写了。当个参考好了。这篇文章有一对多,多对一,单向多对多(我有点懵),双向多对多,以及他们的查询等等,很详细。


二、Flask-SQLAlchemy

Flask-SQLAlchemy 是一个为您的 Flask 应用增加 SQLAlchemy 支持的扩展。它需要 SQLAlchemy 0.6 或者更高的版本。它致力于简化在 Flask 中 SQLAlchemy 的使用,提供了有用的默认值和额外的助手来更简单地完成常见任务。


1. Flask-SQLAlchemy基本操作

1.1 一个简单的示例:


from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 实例化SQLAlchemy
db = SQLAlchemy()
# PS : 实例化SQLAlchemy的代码必须要在引入蓝图之前 app = Flask(__name__) # 配置数据库连接
app.config[”SQLALCHEMY_DATABASE_URI“] = “mysql+pymysql://root:123456@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8mb4” # 初始化SQLAlchemy , 本质就是将以上的配置读取出来
db.init_app(app) # 一个简单的模型
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True) def __init__(self, username, email):
self.username = username
self.email = email def __repr__(self):
return '<User %r>' % self.username # 根据模型在数据库中生成相应的表
db.create_all()

1.2 简单的增删改查

# 导入模型
from your_application import User # 创建数据
admin = User('admin', 'admin@example.com')
guest = User('guest', 'guest@example.com') # 写入到数据库表中
db.session.add(admin)
db.session.add(guest)
db.session.commit() # 查询
users = User.query.all()
# [<User u'admin'>, <User u'guest'>] admin = User.query.filter_by(username='admin').first()
# <User u'admin'>

2. Flask-SQLAlchemy的(一对多)(多对多)

2.1 一对多(one-to-many)关系


class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address', backref='person',
lazy='dynamic') class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

**db.relationship() ** 这个函数返回一个可以做许多事情的新属性。在本案例中,我们让它指向 Address 类并加载多个地址。它如何知道会返回不止一个地址?因为 SQLALchemy 从您的声明中猜测了一个有用的默认值。 如果您想要一对一关系,您可以把 uselist=False 传给 relationship() 。

backref 是一个在 Address 类上声明新属性的简单方法。您也可以使用 my_address.person 来获取使用该地址(address)的人(person)。lazy 决定了 SQLAlchemy 什么时候从数据库中加载数据它的值有:

  • 'select' :(默认值) 就是说 SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据。
  • 'joined' :告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系。
  • 'subquery' :类似 'joined' ,但是 SQLAlchemy 会使用子查询。
  • 'dynamic' :不直接加载这些数据,SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。

详细用法参见:(Flask - SQLalchemy 之 lazy 属性)[https://www.jianshu.com/p/8427da16729a]

为反向引用(backrefs)定义惰性(lazy)状态:使用 backref() 函数:


class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address', backref=db.backref('person', lazy='joined'), lazy='dynamic')

2.2 多对多(many-to-many)关系

如果想要用多对多关系,需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议不使用模型,而是采用一个实际的表:


# 辅助表
post_tag = db.Table('post_tag',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
db.Column('post_id', db.Integer, db.ForeignKey('post.id'))
) # 文章模型
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable = False)
# 假如拿到了一个标签Tag,怎么拿到标签下的所有文章呢.反向引用Article这时用backref
tags = db.relationship('Tag', secondary=post_tag, backref=db.backref('posts', lazy='dynamic')) # 标签模型
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable = False)

其他操作:


article1 = Post(title = 'aaa')
article2 = Article(title = 'bbb')
tag1 = Tag(name = '111')
tag2 = Tag(name = '222') #实现多对多关系,一个post有两个标签
article1.tags.append(tag1)
article1.tags.append(tag2)
article2.tags.append(tag1)
article2.tags.append(tag2) # 增加
db.session.add(article1)
db.session.add(article2)
db.session.add(tag1)
db.session.add(tag2) db.session.commit() # 查询
article1 = Post.query.filter(Post.title == 'aaa').first() tags = article1.tags
for tag in tags:
print(tag.name)

Flask-SQLAlchemy 与 SQL Alchemy 的区别、联系的更多相关文章

  1. Flask学习之旅--还是数据库(sqlacodegen + SQL Alchemy)

    一.写在前面 其实之前已经写过一篇关于 Flask 中使用数据库的博客了,不过那一篇博客主要是记录我在使用 Flask + MySQL8.0 时所遇到的一些问题(如果用的不是 MySQL8.0估计就没 ...

  2. SQL alchemy

    SQL alchemy介绍 SQL alchemy是orm思想的一个具体实现的产品 orm:对象关系映射思想 Object Relational Mapping 就是将数据库里的资源与面向对象中的类和 ...

  3. python第十二周:SQL alchemy、pymysql

    python操作MySQL mysqldb python3之后的版本就不支持mysqldb了,故在此略过 pymysql #执行SQL语句 # -*- coding:utf-8 -*- #!/user ...

  4. Django&,Flask&pyrthon原生sql语句 基本操作

    Django框架 ,Flask框架 ORM 以及pyrthon原生sql语句操作数据库 WHAT IS ORM? ORM( Object Relational Mapping) 对象关系映射 , 即通 ...

  5. flask SQLAlchemy中一对多的关系实现

    SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...

  6. Oracle与Sql server的区别

    一直搞不明白Oracle数据库和sql server的区别,今天我特意查资料把他们的区别整理出来 Oracle数据库:Oracle Database,又名Oracle RDBMS,或简称Oracle. ...

  7. sqlalchemy执行sql语句

    #删除user表中的所有数据,表中的自增字段又从默认值开始 session.execute("truncate table user")

  8. Access、SQLServer、Oracle常见SQL语句应用区别

    Access.SQLServer.Oracle常见SQL语句应用区别 关劲松 PMP 如果要兼容Access.SQL Server.Oracle三个数据库版本:我们在编写SQL语句的过程中,尽量使用一 ...

  9. flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作

    flask, SQLAlchemy, sqlite3 实现 RESTful API, 同时支持form操作. 前端与后台的交互都采用json数据格式,原生javascript实现的ajax.其技术要点 ...

随机推荐

  1. JVM常见面试题及答案

    11.JVM内存分哪几个区,每个区的作用是什么? java虚拟机主要分为以下一个区: 方法区:1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区 ...

  2. Linux自有服务(2)-Linux从入门到精通第六天(非原创)

    文章大纲 一.设置主机名二.chkconfig三.ntp服务四.防火墙服务五.rpm管理(重点)六.cron/crontab计划任务(重点)七.学习资料下载八.参考文章   自有服务,即不需要用户独立 ...

  3. ASM磁盘操作笔记

    添加磁盘组 create diskgroup abc normal redundancy failgroup a disk 'ORCL:AAA' name AAA failgroup b disk ' ...

  4. 重复的DNA序列[哈希表] LeetCode.187

    所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:"ACGAATTCCG".在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数 ...

  5. PAT 乙级 1021.个位数统计 C++/Java

    题目来源 给定一个 k 位整数 1 (0, ,, d​k−1​​>0),请编写程序统计每种不同的个位数字出现的次数.例如:给定 0,则有 2 个 0,3 个 1,和 1 个 3. 输入格式: 每 ...

  6. 用session实现的用户登陆,客户端是怎样获取到cookie信息的

    大家都知道cookie是存在客户端,session存在服务器端.那么客户端具体是怎样获取cookie信息的呢? 更好的阅读体验可访问 这里. 实验环境 实验环境:xampp + Thinkphp5 + ...

  7. [HZOI 2016] 偏序(CDQ套CDQ)

    传送门 思路: 就是cdq套cdq的模板题 #include <bits/stdc++.h> using namespace std; typedef long long ll; cons ...

  8. 使用WIFI网卡的AP功能

    前几篇博客中,wifi无线网卡都工作于STA模式,那么它能否工作于AP模式.本篇博客就研究使wifi 无线网卡工作于AP模式.使用一个应用程序hostapd,关于它的介绍可以去此网站https://w ...

  9. centos7+docker 安装和部署crawlab分布式爬虫平台,并使用docker-compose管理docker

    1.先决条件centos7+docker最新版本 sudo yum updat 2.配置一下镜像源,创建/etc/docker/daemon.conf文件,在其中输入如下内容 { "regi ...

  10. 推荐:Markdown编辑软件 --- 小书匠

    推荐:Markdown编辑软件 --- 小书匠 小书匠 使用手册 Markdown编辑工具推荐小书匠工具,功能丰富,简单使用,可以一步导文件至博客园主页. 概要 小书匠编辑器是一款专为markdown ...