Tornado中sqlalchemy使用

在学tornado的时候涉及以下数据库操作,现在暂时使用mysql数据库,所以选择了一个比较好用的ORM工具sqlalchemy,顺便记一下使用过程

安装

首先安装mysql

pip安装必要的库:pip install sqlalchemy

下载mysql-python驱动: http://www.codegood.com/archives/129 如果是32位版本的windows选win32,如果是64的可以选择amd64

配置

首先需要一个数据库配置文件

# -*- coding: utf-8 -*-
DB_HOST = '127.0.0.1'
# DB_HOST = '127.0.0.1'
DB_USER = 'root'
# DB_USER = 'root'
DB_PWD = ''
# DB_PWD = '084358'
DB_NAME = 'my404'
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() #create Base lei
engine = create_engine('mysql://%s:%s@%s/%s?charset=utf8' %
                   (DB_USER, DB_PWD, DB_HOST, DB_NAME),
                 encoding='utf-8', echo=False,
                   pool_size=100, pool_recycle=10)

这里我写了一个db.py文件,目录在tornado项目根目录下的mod.databases下

接下来是一段类似于orm里实体类部分的代码,我同样放在了mod.databases下,名字为tables.py

from sqlalchemy import Column, String, Integer, VARCHAR,ForeignKey, Float 
from sqlalchemy.orm import relationship,backref
from db import engine,Base

class Article(Base):
    __tablename__ = 'articles'
    user = Column(VARCHAR(20),primary_key = True)
    title = Column(VARCHAR(40))
    time = Column(VARCHAR(20))
    content = Column(VARCHAR(2000))

每个类对应一个表,上方导入必要的库和db里的一些配置信息,注意一定要设置一项为primary_key,不然在查询时会报错Could not assemble any primary key columns for mapped table

这就是大概需要配置的部分,如果需要用新的表就在tables.py里面加入新的类就好了

使用

如下,在自己的main.py里需要对定义的application里面做一下数据库的设置,通过self.db修改属性来设置一些和数据库相关的操作。但是具体其中的属性还不太了解,就先放着了。

class Application(tornado.web.Application):

    def __init__(self):
        handlers = [
        (r"/", IndexHandler),
        ]
        settings = dict(
            debug=True,
            static_path=os.path.join(os.path.dirname(__file__),"static"),
            template_path=os.path.join(os.path.dirname(__file__), "templates")
        )
        tornado.web.Application.__init__(self, handlers, **settings)
        self.db = scoped_session(sessionmaker(bind=engine,
                                              autocommit=False, autoflush=True,
                                              expire_on_commit=False))

if __name__ == '__main__':
    tornado.options.parse_command_line()
    Application().listen(options.port, address='127.0.0.1')
    tornado.ioloop.IOLoop.instance().start()

在具体的handler里使用时如下

from tornado.httpclient import HTTPRequest, AsyncHTTPClient
from mod.databases.tables import Article
import tornado.web
import tornado.gen
import urllib

class DbHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        data = self.db.query(Article).all()
        for item in data:
            print item.content

一方面对使用的实体类要进行导入,如

from mod.databases.tables import Article

另一方面db函数上方

@property

标注是python关于属性的标注,有了这个标注就可以使用self.db来直接获取连接对象,而不需要加上括号self.db(),看起来会比较直观

查询

具体的查询语句就是

data = self.db.query(Article).all()

这里我从数据库里取出数据后只把每一项的content列输出了,并没有进行其他操作。 其他的使用方法可以参考sqlalchemy的官方文档 http://docs.sqlalchemy.org/en/rel_1_0/or...

插入

new_user = User(user_email = email,user_name = name,user_psd = psd)
self.db.add(new_user)
self.db.commit()
self.db.close()#用完后关闭数据库连接,否则可能 导致此次连接时间过长而未操作,数据库连接超时的问题

需要注意的地方是commit函数,如果没有commit,那么self.db里还是保存着之前的信息,这样说似乎不太明白,但是我在使用的过程中发生了一个这样的情景: 我搭建了一个小网站,可以用于注册登录,在我注册时我先检测相关信息是否合法,例如用户名(邮箱)是否已存在:

user = self.db.query(User).filter(User.user_email == self.email).first()
if user!=None:
    表示用户名已存在
    返回错误信息
else:
    用户名不存在,可以注册
    new_user = User(user_email = email,user_name = name,user_psd = psd)
    self.db.add(new_user)
    self.db.commit()

但紧接着,我又做了一件没有什么必要做的事情(请不要吐槽,我只是这么写了一下,其实目的是检测一下这个用户是否在数据库中存在了,然后返回注册成功的信息

user = self.db.query(User).filter(User.user_name == name).first()
if(user.user_email == email):
    self.db.commit()
    data["status"] = 200
    data["data"] = "Register Success"
    标记2
    self.write(data)

但是这么做令我出现了一个麻烦 在我注册成功后,我从数据库中紧接着删除了这个用户,然后重新注册,这时候他显示这个用户还是存在的… 在我将tornado的服务重启后,用同样的用户名去注册,发现这时候又不显示该用户存在了,于是注册成功

之后我在标记2处加了一句self.db.commit()后这个问题就不再出现了。 一般我们还会采取的操作是 原因是因为self.db其实是sqlalchemy的scoped_session,他相当于未commit时有个缓存,查询结果也会缓存在其中。于是虽然数据库里删除了某用户,但是在删除之前我做了一次对这个用户的查询,导致self.db里缓存了这个用户。所以下次他直接在缓存里找到了这个用户。 重启服务后缓存清掉了,也就恢复正常和数据库保持同步了…

具体的原因还得看看文档…如果有知道的同学欢迎指导啊=.=

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

JavaWeb项目架构之Kafka分布式日志队列

架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Kafka做消息队列罢了。

76410
来自专栏Java呓语

第16章、复制

观察到服务器版本略有差异,应用在生产环境时最好将MySQL的版本保持一致。最不济也要保证前两位(5.7)版本保持一致,不要出现主(5.7)从(5.1)这种跨版本...

902
来自专栏技术博文

Linux环境下Swap配置方法

Linux环境下Swap配置方法 场景: 今天下午安装一个CentOS6.5操作系统,忘记配置swap分区。看看如何安装系统之后,增加和删除swap分区...

3546
来自专栏杨建荣的学习笔记

MySQL源码安装总结(r12笔记第12天)

作为一个DBA, MySQL源码安装还是要做做的,虽然不是推荐线上批量安装部署,但是自己作为了解MySQL的一个学习过程,还是值得的。 相比商业...

3117
来自专栏程序猿

SQLmap命令的介绍

SQLmap这个工具的使用。(结尾有彩蛋) URL---> 判断注入的参数, 判断是使用的那种SQL注入 识别出那种数据库 根据用户的选择,读出数据 五种注入模...

3123
来自专栏吕亚辉的专栏

【腾讯云的1001种玩法】CRUD生成器DBuilder介绍与腾讯云部署

Dbuilder是基于laravel4开发的一套快速实现数据库表CRUD(增删改查)操作的工具,核心思想是做到针对数据库表的每个字段做到精确配置,通过生成字段配...

3610
来自专栏黑泽君的专栏

day66_Solr学习笔记

目录结构详解如下:   bin:solr的运行脚本。   contrib:solr的一些扩展jar包,用于增强solr的功能。   dist:该目录包含bui...

1164
来自专栏Netkiller

Apache Hbase 快速入门

本文节选自《Netkiller Database 手札》 ? 第 62 章 Apache Hbase 目录 62.1. 安装 Apache Hbase 62...

3556
来自专栏个人分享

工作中Linux常用命令

 rpm -ev mysql-server-5.1.73-5.el6_6.x86_64

1183
来自专栏Java架构师历程

ssh工作原理

1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件

1313

扫码关注云+社区

领取腾讯云代金券