没使用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中指定编码:
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_by
和filter
的区别
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