偷闲加油站 發表於 2019-11-10 21:54:00

Python SQLAlchemy入门教程

<p>本文将以Mysql举例,介绍sqlalchemy的基本用法。其中,Python版本为2.7,sqlalchemy版本为1.1.6。</p>
<h2 id="一-介绍">一. 介绍</h2>
<p>SQLAlchemy是Python中最有名的ORM工具。</p>
<p><strong>关于ORM:</strong></p>
<p>全称Object Relational Mapping(对象关系映射)。</p>
<p>特点是操纵Python对象而不是SQL查询,也就是在代码层面考虑的是对象,而不是SQL,体现的是一种程序化思维,这样使得Python程序更加简洁易读。</p>
<p>具体的实现方式是将数据库表转换为Python类,其中数据列作为属性,数据库操作作为方法。</p>
<p>**优点: **</p>
<ol>
<li>简洁易读:将数据表抽象为对象(数据模型),更直观易读</li>
<li>可移植:封装了多种数据库引擎,面对多个数据库,操作基本一致,代码易维护</li>
<li>更安全:有效避免SQL注入</li>
</ol>
<p><strong>为什么要用sqlalchemy?</strong></p>
<p>虽然性能稍稍不及原生SQL,但是操作数据库真的很方便!</p>
<h2 id="二-使用">二. 使用</h2>
<h3 id="概念和数据类型">概念和数据类型</h3>
<p>概念</p>
<table>
<thead>
<tr>
<th>概念</th>
<th>对应数据库</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Engine</td>
<td>连接</td>
<td>驱动引擎</td>
</tr>
<tr>
<td>Session</td>
<td>连接池,事务</td>
<td>由此开始查询</td>
</tr>
<tr>
<td>Model</td>
<td>表</td>
<td>类定义</td>
</tr>
<tr>
<td>Column</td>
<td>列</td>
<td></td>
</tr>
<tr>
<td>Query</td>
<td>若干行</td>
<td>可以链式添加多个条件</td>
</tr>
</tbody>
</table>
<p>常见数据类型</p>
<table>
<thead>
<tr>
<th>数据类型</th>
<th>数据库数据类型</th>
<th>python数据类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Integer</td>
<td>int</td>
<td>int</td>
<td>整形,32位</td>
</tr>
<tr>
<td>String</td>
<td>varchar</td>
<td>string</td>
<td>字符串</td>
</tr>
<tr>
<td>Text</td>
<td>text</td>
<td>string</td>
<td>长字符串</td>
</tr>
<tr>
<td>Float</td>
<td>float</td>
<td>float</td>
<td>浮点型</td>
</tr>
<tr>
<td>Boolean</td>
<td>tinyint</td>
<td>bool</td>
<td>True / False</td>
</tr>
<tr>
<td>Date</td>
<td>date</td>
<td>datetime.date</td>
<td>存储时间年月日</td>
</tr>
<tr>
<td>DateTime</td>
<td>datetime</td>
<td>datetime.datetime</td>
<td>存储年月日时分秒毫秒等</td>
</tr>
<tr>
<td>Time</td>
<td>time</td>
<td>datetime.datetime</td>
<td>存储时分秒</td>
</tr>
</tbody>
</table>
<h3 id="使用步骤">使用步骤</h3>
<h4 id="创建数据库表">创建数据库表</h4>
<p>**1.安装 **</p>
<p><code>pip install SQLalchemy</code></p>
<p><strong>2. 创建连接</strong></p>
<pre><code class="language-python">from sqlalchemy import create_engine

engine = create_engine("mysql://user:password@hostname/dbname?charset=utf8")
</code></pre>
<p>这行代码初始化创建了Engine,Engine内部维护了一个Pool(连接池)和Dialect(方言),方言来识别具体连接数据库种类。</p>
<p>创建好了Engine的同时,Pool和Dialect也已经创建好了,但是此时并没有真正与数据库连接,等到执行具体的语句.connect()等时才会连接到数据库。</p>
<p>create_engine还有其它可选的参数,比如:</p>
<pre><code class="language-python">engine = create_engine("mysql://user:password@hostname/dbname?charset=utf8",
                     echo=True,
                     pool_size=8,
                     pool_recycle=60*30
                     )
</code></pre>
<ol>
<li>echo: 当设置为True时会将orm语句转化为sql语句打印,一般debug的时候可用</li>
<li>pool_size: 连接池的大小,默认为5个,设置为0时表示连接无限制</li>
<li>pool_recycle: 设置时间以限制数据库多久没连接自动断开</li>
</ol>
<p><strong>3. 创建数据库表类(模型)</strong></p>
<p>前面有提到ORM的重要特点,那么我们操作表的时候就需要通过操作对象来实现,现在我们来创建一个类,以常见的用户表举例:</p>
<pre><code class="language-python">from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Users(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True)
    email = Column(String(64))

    def __init__(self, name, email):
      self.name = name
      self.email = email

</code></pre>
<p>declarative_base()是sqlalchemy内部封装的一个方法,通过其构造一个基类,这个基类和它的子类,可以将Python类和数据库表关联映射起来。</p>
<p>数据库表模型类通过__tablename__和表关联起来,Column表示数据表的列。</p>
<p><strong>4. 生成数据库表</strong></p>
<p><code>Base.metadata.create_all(engine)</code></p>
<p>创建表,如果存在则忽略,执行以上代码,就会发现在db中创建了users表。</p>
<h4 id="操作数据">操作数据</h4>
<p>表创建好了就是操作数据了,常见的操作增删改查,我们一一介绍。</p>
<p><strong>session</strong></p>
<p>sqlalchemy中使用session用于创建程序和数据库之间的会话,所有对象的载入和保存都需要通过session对象 。</p>
<p>通过sessionmaker调用创建一个工厂,并关联Engine以确保每个session都可以使用该Engine连接资源:</p>
<pre><code>from sqlalchemy.orm import sessionmaker

# 创建session
DbSession = sessionmaker(bind=engine)
session = DbSession()
</code></pre>
<p>session的常见操作方法包括:</p>
<ol>
<li>flush:预提交,提交到数据库文件,还未写入数据库文件中</li>
<li>commit:提交了一个事务</li>
<li>rollback:回滚</li>
<li>close:关闭</li>
</ol>
<p><strong>增</strong></p>
<p>举个最简单的例子:</p>
<pre><code>add_user = Users("test", "test123@qq.com")
session.add(add_user)
session.commit()
</code></pre>
<p>session.add()将会把Model加入当前session维护的持久空间(可以从session.dirty看到)中,直到commit时提交到数据库。</p>
<p>Q1:add之后如何直接返回对象的属性?</p>
<p>可以在add之后执行db.session.flush(),这样便可在session中get到对象的属性。</p>
<p>Q2:如何进行批量插入,性能比较?</p>
<p>批量插入共有以下几种方法,对它们的批量做了比较,分别是:</p>
<p>session.add_all() &lt; bulk_save_object() &lt; bulk_insert_mappings() &lt; SQLAlchemy_core()</p>
<p><strong>查</strong></p>
<p>查询是最常用的一个操作了,举个最简单的查询例子:</p>
<pre><code class="language-python">users = session.query(Users).filter_by(id=1).all()
for item in users:
    print(item.name)
</code></pre>
<p>通常我们通过以上查询模式获取数据,需要注意的是,通过session.query()我们查询返回了一个Query对象,此时还没有去具体的数据库中查询,只有当执行具体的.all(),.first()等函数时才会真的去操作数据库。</p>
<p>其中,query有filter和filter_by两个过滤方法,上述例子也可写为:</p>
<pre><code class="language-python">users = session.query(Users).filter_by(Users.id == 1).all()
</code></pre>
<p>通常这两个方法都会用到的,所以一定要掌握它们的区别:</p>
<table>
<thead>
<tr>
<th style="text-align: center">filter</th>
<th style="text-align: center">filter_by</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">支持所有比较运算符,相等比较用比较用==</td>
<td style="text-align: center">只能使用"=","!="和"&gt;&lt;"</td>
</tr>
<tr>
<td style="text-align: center">过滤用类名.属性名</td>
<td style="text-align: center">过滤用属性名</td>
</tr>
<tr>
<td style="text-align: center">不支持组合查询,只能连续调用filter变相实现</td>
<td style="text-align: center">参数是**kwargs,支持组合查询</td>
</tr>
<tr>
<td style="text-align: center">支持and,or和in等</td>
<td style="text-align: center"></td>
</tr>
</tbody>
</table>
<p><strong>改</strong></p>
<p>更新数据有两种方法,一种是使用query中的update方法:</p>
<pre><code>session.query(Users).filter_by(id=1).update({'name': "Jack"})
</code></pre>
<p>另一种是操作对应的表模型:</p>
<pre><code>users = session.query(Users).filter_by(name="Jack").first()
users.name = "test"
session.add(users)
</code></pre>
<p>这两种方式呢,一般批量更新的话我会选前者,而要对查询获取对象属性之后再更新的场景就需要使用后者。</p>
<p><strong>删</strong></p>
<p>和更新数据类似,删除数据也有两种方法,第一种:</p>
<pre><code class="language-python">delete_users = session.query(Users).filter(Users.name == "test").first()
if delete_users:
    session.delete(delete_users)
    session.commit()
</code></pre>
<p>第二种:</p>
<pre><code>session.query(Users).filter(Users.name == "test").delete()
session.commit()
</code></pre>
<p>批量删除时推荐使用第二种。</p>
<p>以上,就是Python sqlalchemy的基本用法。</p>
<p>代码可参照:my github</p><br><br>
来源:https://www.cnblogs.com/ybjourney/p/11832045.html
頁: [1]
查看完整版本: Python SQLAlchemy入门教程