前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Tornado中sqlalchemy使用

Tornado中sqlalchemy使用

作者头像
NaOH
发布2018-05-29 13:18:20
1.5K0
发布2018-05-29 13:18:20
举报

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

安装

首先安装mysql

pip安装必要的库:pip install sqlalchemy

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

配置

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

代码语言:javascript
复制
# -*- 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'
代码语言:javascript
复制
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

代码语言:javascript
复制
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修改属性来设置一些和数据库相关的操作。但是具体其中的属性还不太了解,就先放着了。

代码语言:javascript
复制
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里使用时如下

代码语言:javascript
复制
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

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

代码语言:javascript
复制
from mod.databases.tables import Article

另一方面db函数上方

代码语言:javascript
复制
@property

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

查询

具体的查询语句就是

代码语言:javascript
复制
data = self.db.query(Article).all()

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

插入
代码语言:javascript
复制
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里还是保存着之前的信息,这样说似乎不太明白,但是我在使用的过程中发生了一个这样的情景: 我搭建了一个小网站,可以用于注册登录,在我注册时我先检测相关信息是否合法,例如用户名(邮箱)是否已存在:

代码语言:javascript
复制
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()

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

代码语言:javascript
复制
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里缓存了这个用户。所以下次他直接在缓存里找到了这个用户。 重启服务后缓存清掉了,也就恢复正常和数据库保持同步了…

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年10月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装
  • 配置
  • 使用
    • 查询
      • 插入
      相关产品与服务
      云数据库 SQL Server
      腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档