cherrypy@Tutorial 9: Data is all my life

关注微信公众号(瓠悠笑软件部落),一起学习,一起摸鱼
huyouxiao.com
到目前为止,所有生成的字符串都保存在会话中,默认情况下会话存储在进程内存中。 但是,您可以在磁盘或分布式内存存储中保留会话,但这不是长期保持数据的正确方法。 会话用于识别您的用户并携带用户所执行操作所需的少量数据。

要存储,保存和查询数据,您需要一个合适的数据库服务器。 有各种范例支持可供选择:
关系型数据库:PostgreSQL,SQLite,MariaDB,Firebird
列导向型数据库:HBase,Cassandra
key-store型数据库:redis,memcached
面向文档型数据库:Couchdb,MongoDB
图形导向型数据库:neo4j

让我们关注关系型数据库,因为它们是最常见的,也可能是您首先要学习的内容。
为了减少这些教程的依赖项数量,我们将使用Python直接支持的sqlite数据库。
我们的应用程序将把会话中生成的字符串的存储替换为SQLite数据库。 该应用程序将具有与教程08相同的HTML代码。因此,我们只关注应用程序代码本身:

#! /usr/bin/python3
import os, os.path
import random
import sqlite3
import string
import time

import cherrypy

DB_STRING = "my.db"

class StringGenerator(object):
    @cherrypy.expose
    def index(self):
        return open('index.html')

@cherrypy.expose
class StringGeneratorWebService(object):

    @cherrypy.tools.accept(media='text/plain')
    def GET(self):
        with sqlite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            r = c.execute("SELECT value FROM user_string WHERE session_id=?", [cherrypy.session.id])
            return r.fetchone()

    def POST(self, length=8):
        some_string = ''.join(random.sample(string.hexdigits, int(length)))
        with sqllite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            c.execute("INSERT INTO user_string VALUES (?, ?)", [cherrypy.session.id, some_string])
        return some_string

    def PUT(self, another_string):
        with sqlite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            c.execute("UPDATE user_string SET value=? WHERE session_id=?", [another_string, cherrypy.session.id])

    def DELETE(self):
        cherrypy.session.pop('ts', None)
        with sqlite3.connect(DB_STRING) as c:
            c.execute("DELETE FROM user_string WHERE session_id=?", [cherrypy.session.id])

def setup_database():
    """
    Create the `user_string` table in the database
    on server startup
    """
    with sqlite3.connect(DB_STRING) as con:
        con.execute("CREATE TABLE user_string (session_id, value)")

def cleanup_database():
   """
   Destroy the `user_string` table from the database
   on server shutdown.
   """
   with sqlite3.connect(DB_STRING) as con:
      con.execute("DROP TABLE user_string")

if __name__ == '__main__':
   conf = {
    '/': {
            'tools.sessions.on': True,
            'tools.staticdir.root': os.path.abspath(os.getcwd())
        },
        '/generator': {
            'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            'tools.response_headers.on': True,
            'tools.response_headers.headers': [('Content-Type', 'text/plain')],
        },
        '/static': {
            'tools.staticdir.on': True,
            'tools.staticdir.dir': './public'
        }
   }

   cherrypy.engine.subscribe('start', setup_database)
   cherrypy.engine.subscribe('stop', cleanup_database)
    
   webapp = StringGenerator()
   webapp.generator = StringGeneratorWebService()
   cherrypy.quickstart(webapp, '/', conf)

将其保存到名为tut09.py的文件中,并按如下方式运行:

$ python tut09.py

让我们首先看看我们如何创建两个在数据库中创建和销毁表的函数。 这些函数在86-87行注册到CherryPy的服务器,以便在服务器启动和停止时调用它们。

接下来,请注意我们如何使用对数据库的调用替换所有会话代码。 我们使用会话ID来识别数据库中用户的字符串。 由于会议将在一段时间后消失,这可能不是正确的方法。 更好的想法是关联用户的登录或更具弹性的唯一标识符。 为了我们的演示,这应该做。

重要
在此示例中,我们仍然必须将会话设置为虚拟值,以便CherryPy不会在每个请求上丢弃会话。 由于我们现在使用数据库来存储生成的字符串,因此我们只是在会话中存储虚拟时间戳。

注意
不幸的是,Python中的sqlite禁止我们共享线程之间的连接。 由于CherryPy是一个多线程服务器,这将是一个问题。 这就是我们在每次调用时打开和关闭数据库连接的原因。 这显然不是生产友好的,并且建议使用功能更强大的数据库引擎或更高级别的库(如SQLAlchemy)来更好地支持应用程序的需求。

猜你喜欢

转载自blog.csdn.net/fudaxing/article/details/88649253