Python第三方ORM库:SQLAlchemy简介

版权声明:本文为 [onefine] 原创文章,转载请注明出处: https://blog.csdn.net/jiduochou963/article/details/88637702

没使用orm之前:
待补充

一、ORM介绍

…介绍详百度百科
主要实现:

  • SqlObject
  • peewee
  • Django’s ORM
  • SQLAlchemy

SQLAlchemy官网: https://docs.sqlalchemy.org/

二、SQLAlchemy安装及配置

1、原理图

在这里插入图片描述

安装

pip install SQLAlchemy

测试及版本查看

In [1]: import sqlalchemy

In [2]: sqlalchemy.__version__
Out[2]: '1.3.1'

In [3]:

三、ORM模型介绍

常见类型

  • Integer
  • Float
  • Boolean
  • ForeignKey
  • Date/DateTime
  • String

更多数据类型: https://docs.sqlalchemy.org/en/latest/core/type_basics.html

# 待补充

四、通过ORM新增数据到数据库

文档:

https://docs.sqlalchemy.org/en/latest/orm/tutorial.html
https://docs.sqlalchemy.org/en/latest/core/engines.html
https://docs.sqlalchemy.org/en/latest/core/engines.html#sqlalchemy.create_engine


创建ORM模型

spider_pjt3_lagou.spider_test.test_1.py中:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Boolean

engine = create_engine('mysql://urername:pwd@localhost:port/database')
Base = declarative_base()  # 获取基类


class News(Base):
    __tablename__ = 'news_test'  # 定义表名
    id = Column('news_id', Integer, primary_key=True)  # 参数可选,如果没有则采用变量名作为数据库的字段名
    title = Column(String(200), nullable=False)  # 非空
    content = Column(String(2000), nullable=False)
    types = Column(String(10), nullable=False)
    image = Column(String(300), )
    author = Column(String(20), )
    view_count = Column(Integer)
    create_at = Column(DateTime)
    is_valid = Column(Boolean)

Python Console中:

>>> from spider_pjt3_lagou.spider_test.test_1 import News
>>> from spider_pjt3_lagou.spider_test.test_1 import engine
>>> News.metadata.create_all(engine)

>>> 

MySQL 8.0 Command Line Client中测试:

mysql> USE database;
Database changed
mysql> DESC news_test;
+------------+---------------+------+-----+---------+----------------+
| Field      | Type          | Null | Key | Default | Extra          |
+------------+---------------+------+-----+---------+----------------+
| news_id    | int(11)       | NO   | PRI | NULL    | auto_increment |
| title      | varchar(200)  | NO   |     | NULL    |                |
| content    | varchar(2000) | NO   |     | NULL    |                |
| types      | varchar(10)   | NO   |     | NULL    |                |
| image      | varchar(300)  | YES  |     | NULL    |                |
| author     | varchar(20)   | YES  |     | NULL    |                |
| view_count | int(11)       | YES  |     | NULL    |                |
| create_at  | datetime      | YES  |     | NULL    |                |
| is_valid   | tinyint(1)    | YES  |     | NULL    |                |
+------------+---------------+------+-----+---------+----------------+
9 rows in set (0.01 sec)

mysql>

新增数据

from sqlalchemy.orm import sessionmaker
engine = create_engine('mysql://urername:pwd@localhost:port/database')
Session = sessionmaker(bind=engine)

class OrmTest(object):

    def __init__(self):
        self.session = Session()

    def add_one(self):
        """新增记录"""
        new_obj = News(
            title='标题',
            content='内容',
            types='ORM测试',
        )
        self.session.add(new_obj)
        self.session.commit()
        return new_obj

测试:

(Py3_spider) > python test_1.py
Traceback (most recent call last):
  File "test_1.py", line 60, in <module>
    main()
  File "test_1.py", line 55, in main
    rest = obj.add_one()
  File "test_1.py", line 49, in add_one
    self.session.commit()
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 1026, in commit
    self.transaction.commit()
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 493, in commit
    self._prepare_impl()
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 472, in _prepare_impl
    self.session.flush()
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 2451, in flush
    self._flush(objects)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 2589, in _flush
    transaction.rollback(_capture_exception=True)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\util\langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\util\compat.py", line 129, in reraise
    raise value
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\session.py", line 2549, in _flush
    flush_context.execute()
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 422, in execute
    rec.execute(self)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 589, in execute
    uow,
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\persistence.py", line 245, in save_obj
    insert,
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\orm\persistence.py", line 1120, in _emit_insert_statements
    statement, params
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\base.py", line 988, in execute
    return meth(self, multiparams, params)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\sql\elements.py", line 287, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\base.py", line 1107, in _execute_clauseelement
    distilled_params,
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\base.py", line 1248, in _execute_context
    e, statement, parameters, cursor, context
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\base.py", line 1468, in _handle_dbapi_exception
    util.reraise(*exc_info)
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\util\compat.py", line 129, in reraise
    raise value
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\base.py", line 1244, in _execute_context
    cursor, statement, parameters, context
  File "Envs\Py3_spider\lib\site-packages\sqlalchemy\engine\default.py", line 552, in do_execute
    cursor.execute(statement, parameters)
  File "Envs\Py3_spider\lib\site-packages\MySQLdb\cursors.py", line 191, in execute
    args = tuple(map(db.literal, args))
  File "Envs\Py3_spider\lib\site-packages\MySQLdb\connections.py", line 238, in literal
    s = self.string_literal(o.encode(self.encoding))
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-1: ordinal not in range(256)

(Py3_spider) >

由于中文的原因,编码方面出问题,在engine中指定编码:

扫描二维码关注公众号,回复: 5638965 查看本文章
create_engine('mysql://urername:pwd@localhost:port/database?charset=utf8')

然后:

(Py3_spider) > python test_1.py
1

(Py3_spider) > python test_1.py
2

(Py3_spider) > 

查看数据库:

mysql> select * from news_test;
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
| news_id | title | content | types   | image | author | view_count | create_at | is_valid |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
|       1 | 标题  | 内容    | ORM测试 | NULL  | NULL   |       NULL | NULL      |     NULL |
|       2 | 标题  | 内容    | ORM测试 | NULL  | NULL   |       NULL | NULL      |     NULL |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
2 rows in set (0.00 sec)

mysql>

查询数据

查询一条数据:
class OrmTest(object):
    ...
    def get_one(self):
        """查询一条数据"""
        return self.session.query(News).get(1)  # 按照主键来获取


def main():
    obj = OrmTest()
    rest = obj.get_one()
    print('ID:{0}=>{1}'.format(rest.id, rest.title))

if __name__ == '__main__':
    main()

结果:

(Py3_spider) > python test_1.py
ID:1=>标题

(Py3_spider) > 

如果获取不存在的数据:

def get_one(self):
	return self.session.query(News).get(13)

结果:

(Py3_spider) > python test_1.py
Traceback (most recent call last):
  File "test_1.py", line 64, in <module>
    main()
  File "test_1.py", line 60, in main
    print('ID:{0}=>{1}'.format(rest.id, rest.title))
AttributeError: 'NoneType' object has no attribute 'id'

(Py3_spider) spider_test >

所以,可以对查询的结果做判断:

def main():
    obj = OrmTest()
    rest = obj.get_one()
    if rest:
        print('ID:{0}=>{1}'.format(rest.id, rest.title))
    else:
        print('Not exist.')
查询多条数据:
class OrmTest(object):
	...
    def get_more(self):
        """查询多条数据"""
        return self.session.query(News).filter_by(is_valid=None)  # is_valid是数据库的字段,None、False、True、0、1


def main():
    obj = OrmTest()
    rests = obj.get_more()
    if rests:
    	print('count:', rests.count())
        for rest in rests:
            print('ID:{0}=>{1}'.format(rest.id, rest.title))
    else:
        print('Not exist.')

结果:

(Py3_spider) > python test_1.py
count: 2
ID:1=>标题
ID:2=>标题


(Py3_spider) spider_test >

注意filter_byfilter的区别

filter_by(is_valid=None)
filter(is_valid==0)

修改和删除数据

修改:
class OrmTest(object):
	...
    def upadate_data(self, pk):
        """修改数据"""
        new_obj = self.session.query(News).get(pk)  # 获取要修改的数据
        if new_obj:
            new_obj.is_valid = 0  # 逻辑删除
            self.session.add(new_obj)
            self.session.commit()
            return True
        return False  # 要修改的对象不存在


def main():
    obj = OrmTest()
    rest = obj.upadate_data(1)
    if rest:
        print("修改成功")
    else:
        print("失败")

执行之后:

mysql> select * from news_test;
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
| news_id | title | content | types   | image | author | view_count | create_at | is_valid |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
|       1 | 标题  | 内容    | ORM测试 | NULL  | NULL   |       NULL | NULL      |        0 |
|       2 | 标题  | 内容    | ORM测试 | NULL  | NULL   |       NULL | NULL      |     NULL |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
2 rows in set (0.00 sec)

mysql>
删除:
class OrmTest(object):
	...
    def delete_data(self, pk):
        """删除数据"""
        new_obj = self.session.query(News).get(pk)  # 获取要删除的数据
        if new_obj:
            self.session.delete(new_obj)
            self.session.commit()
            return True
        else:
            return False

def main():
    obj = OrmTest()
    rest = obj.delete_data(2)
    if rest:
        print("删除成功")
    else:
        print("删除失败")

执行之后:

mysql> select * from news_test;
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
| news_id | title | content | types   | image | author | view_count | create_at | is_valid |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
|       1 | 标题  | 内容    | ORM测试 | NULL  | NULL   |       NULL | NULL      |        0 |
+---------+-------+---------+---------+-------+--------+------------+-----------+----------+
1 row in set (0.00 sec)

mysql>

推荐参考:

SQLAlchemy技术文档(中文版)(上) http://www.cnblogs.com/iwangzc/p/4112078.html
SQLAlchemy技术文档(中文版)(中) https://www.cnblogs.com/iwangzc/p/4114913.html
使用sqlalchemy用orm方式写pipeline将scrapy item快速存入 MySQL https://blog.csdn.net/lhs960124/article/details/80383833

python orm模型SQLAlchemy https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0014021031294178f993c85204e4d1b81ab032070641ce5000

SQLAlchemy使用教程 https://www.cnblogs.com/mrchige/p/6389588.html

python 数据库连接池DBUtils https://cito.github.io/DBUtils/UsersGuide.html

猜你喜欢

转载自blog.csdn.net/jiduochou963/article/details/88637702