目录
前言
手册目录:
软件下载及环境安装:
实习手册一(基于Tornado框架的接口响应服务)软件下载与环境配置
Tornado基本框架搭建:
实习手册二(基于Tornado框架的接口响应服务)Tornado基本框架的搭建
Tornado框架中日志的记录,路由的分发,接口的响应:
实习手册三(基于Tornado框架的接口响应服务)Tornado框架中日志的记录,路由的分发,接口的响应
通过PyMySQL,SQLAlchemy在PyCharm中实现对数据的增删改查:
实习手册四(基于Tornado框架的接口响应服务)通过PyMySQL,SQLAlchemy在PyCharm中实现对数据的增删改查
SqlAlchemy的再封装,PyMySQL和SqlAlchemy的结合使用:
实习手册五(基于Tornado框架的接口响应服务)SqlAlchemy的再封装,PyMySQL和SqlAlchemy的结合使用
在Tornado实现对数据库的操作功能:
实习手册六(基于Tornado框架的接口响应服务)在Tornado实现对数据库的操作功能
不知不觉已经到实习手册七了,本章我们要实现利用redis来对数据进行缓存。
Redis
Redis简介
简而言之,redis也跟我们的mysql一样,是一种数据库,跟mysql不同的是,redis是一款高性能的NOSQL系列的非关系型数据库,它是利用内存来存储数据的,而mysql是利用磁盘来存储数据的,这样的特性使得我们利用redis进行数据查询时,速度会比利用mysql要快得多。
Redis的下载及安装已在实习手册一中介绍过,这里不再赘述。
Python操作redis
没有学习过redis的同学可以点击下方这个链接系统化地学习一下:
使用redis后,我们的数据库查询步骤应该变成这样:
获取到查询请求→将请求传递的参数转化为key→将key传入到查询接口→查询接口调用query方法→先去redis中进行查询,看是否有数据,有则返回,无则去mysql中进行查询,还没有就返回无结果
因此,我们先确定key的格式,key应该是由select语句中的主要参数构成:查什么+去哪查+筛选条件
这里我们以查询用户id,用户名,创建时间为例来进行演示:
# User表数据模型
class User(SqlAchBase().base, MysqlBase):
__tablename__ = 'user'
userid = Column(Integer, autoincrement=True, primary_key=True)
uname = Column(String(30))
pwd = Column(String(30))
create_time = Column(String(30))
def search_user(self):
# 获取表名(去哪查)
table_name = User.__tablename__
# 获取请求参数
uname = self.get_argument('uname')
userid = self.get_argument('userid')
# key建立:查询内容+查询表
key = 'uname,userid,create_time' + '|' + table_name
# 判断筛选条件是否存在,存在的话就拼接到key中
if uname:
key += '|' + 'uname="{}"'.format(uname)
if userid:
key += '|' + 'userid={}'.format(userid)
# 获取查询结果
result = User.query(key, *[User.userid, User.uname, User.create_time])
# 将结果呈现出来
self.write(str(result))
因为查询一般调用的是get请求,所以获取参数的方式变成了self.get_argument('参数名称')
然后是MysqlBase中的query方法更改:
@classmethod
def query(cls, key, *columns):
cls.TestConn()
search_list = key.split('|')
# 判断是否获取的到这个key
if RedisBase.get(key):
print('successfully get data from redis')
return RedisBase.get(key)
else:
item_list = cls.session.query(*columns or cls).filter(text(search_list[2]+' and '+search_list[3])).all()
print(item_list)
RedisBase.set(key, str(item_list), expire_time=10)
return item_list
然后是RedisBase:
import redis
from settings.config import redis_host, redis_port
class RedisBase():
redis_tool = None
@classmethod
def TestConn(cls):
if cls.redis_tool:
print("already connect to redis_tool\n")
pass
else:
pool = redis.ConnectionPool(host=redis_host, port=redis_port, db=0, decode_responses=True)
cls.redis_tool = redis.Redis(connection_pool=pool)
print("trying to connect to redis_tool\n")
@classmethod
def get(cls, key):
cls.TestConn()
return cls.redis_tool.get(key)
@classmethod
def set(cls, key, target, expire_time):
cls.TestConn()
cls.redis_tool.set(key, target, ex=expire_time)
@classmethod
def expire_seconds(cls, key):
cls.TestConn()
# 查询某个键的剩余时间
return cls.redis_tool.ttl(key)
@classmethod
def keys(cls):
cls.TestConn()
return cls.redis_tool.keys()
@classmethod
def delete(cls, key):
cls.TestConn()
cls.redis_tool.delete(key)
@classmethod
def exists(cls, key):
cls.TestConn()
return cls.redis_tool.exists(key)
然后开启redis服务,在访达中前往/usr/local/bin中打开redis-cli和redis-server两个文件,启动redis服务:
然后在Postman中输入对应的参数,点击Send:
可以看到,我们已经成功查询到了对应的数据。
完整的代码如下:
import redis
from tornado.web import RequestHandler
from tornado.web import Application
from tornado.ioloop import IOLoop
import pymysql
from sqlalchemy import create_engine, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import MetaData
from sqlalchemy import Column, String, Integer
# Redis部分
class RedisBase():
redis_tool = None
redis_host = '127.0.0.1'
redis_port = 6379
@classmethod
def TestConn(cls):
if cls.redis_tool:
print("already connect to redis_tool\n")
pass
else:
pool = redis.ConnectionPool(host=cls.redis_host, port=cls.redis_port, db=0, decode_responses=True)
cls.redis_tool = redis.Redis(connection_pool=pool)
print("trying to connect to redis_tool\n")
# 获取键
@classmethod
def get(cls, key):
cls.TestConn()
return cls.redis_tool.get(key)
# 添加键
@classmethod
def set(cls, key, target, expire_time):
cls.TestConn()
cls.redis_tool.set(key, target, ex=expire_time)
# 查询键剩余时间
@classmethod
def expire_seconds(cls, key):
cls.TestConn()
# 查询某个键的剩余时间
return cls.redis_tool.ttl(key)
# 返回全部键
@classmethod
def keys(cls):
cls.TestConn()
return cls.redis_tool.keys()
# 删除键
@classmethod
def delete(cls, key):
cls.TestConn()
cls.redis_tool.delete(key)
# 判断键是否存在
@classmethod
def exists(cls, key):
cls.TestConn()
return cls.redis_tool.exists(key)
# SqlAch部分
# URL用来作为SqlAlchemy创造引擎的url
# 格式为:"mysql+pymysql://root:你的mysql密码@localhost:3306/数据库名字"
URL = "mysql+pymysql://root:你的密码@localhost:3306/数据库名字"
class SqlAchBase():
engine = create_engine(URL)
base = declarative_base()
session = sessionmaker(bind=engine)()
metadata = MetaData()
@classmethod
def get_session(cls):
return cls.session
# Mysql部分
class MysqlBase():
session = SqlAchBase.get_session()
conn = None
# 测试连接方法
@classmethod
def TestConn(cls):
if not cls.conn:
cls.conn = pymysql.connect(user='root', host='localhost', password=你的密码, db=数据库名称, port=3306)
print("trying to connect to '%s'" % cls.conn)
else:
print("already connected to '%s'" % cls.conn)
# 增
@classmethod
def add(cls, user):
cls.TestConn()
cls.session.add(user)
cls.session.commit()
# 删
@classmethod
def delete(cls, filter):
cls.TestConn()
cls.session.query(cls).filter(text(filter)).delete(synchronize_session=False)
cls.session.commit()
# 改
@classmethod
def update(cls, filter, value):
cls.TestConn()
cls.session.query(cls).filter(text(filter)).update(value, synchronize_session=False)
cls.session.commit()
# 查
@classmethod
def query(cls, key, *columns):
cls.TestConn()
search_list = key.split("|")
if RedisBase.get(key):
print('successfully get data from redis')
return RedisBase.get(key)
else:
item_list = cls.session.query(*columns or cls).filter(text(search_list[2] + ' and ' + search_list[3])).all()
print(item_list)
RedisBase.set(key, str(item_list), expire_time=10)
return item_list
# User数据模型
class User(SqlAchBase().base, MysqlBase):
__tablename__ = 'user'
userid = Column(Integer, autoincrement=True, primary_key=True)
uname = Column(String(30))
pwd = Column(String(30))
create_time = Column(String(30))
# Tornado框架
class SearchHandler(RequestHandler):
# get请求分发
def get(self, *args, **kwargs):
path = self.request.path.split('/')
method = path[-1]
if callable(getattr(self, method)):
getattr(self, method)()
else:
self.write("404 not found")
# search_user接口
def search_user(self):
table_name = User.__tablename__
uname = self.get_argument('uname')
userid = self.get_argument('userid')
key = 'uname,userid,create_time' + '|' + table_name
if uname:
key += '|' + 'uname="{}"'.format(uname)
if userid:
key += '|' + 'userid={}'.format(userid)
print(key)
result = User.query(key, *[User.userid, User.uname, User.create_time])
self.write(str(result))
app = Application([
(r'/user/search/.*', SearchHandler)
])
if __name__ == '__main__':
app.listen(8000)
IOLoop.current().start()
当然,你也可以自己设定redis中键存在的时间,根据需求进行更改就行。
结语
至此,所有的分区板块都已经讲完,接下来将会进入整体项目,会有规范的项目目录,终于不需要将所有代码打在一个程序里了:)。