Databases

Bottle offers persistent storage of key/value pairs using the bottle.db module variable.

The module variable bottle.db gives access to any number of databases objects, each one stored in bottle.db.database_name. The database objects behave like mappings (dictionaries), except that keys are always strings and values must be pickle-able. Printing a database object doesn’t print the keys and values, and the items() and values() methods are not supported.

You can use keys or attributes to access the databases values. Both bottle.db.db_name.key_name and bottle.db[db_name][key_name] will work the same. Missing databases are created on demand, so you don’t have to check for the existence of a database or create one explicitly. Missing keys will raise KeyError as expected.

Persistence

During a request live-cycle, all changes to the databases are cached in thread-local memory. At the end of the request, the changes are saved automatically so the next request will have access to the updated values. Databases are stored in files located in `bottle.DB_PATH`. Be sure to allow write-access to this path.

Race conditions

You don’t have do worry about file corruption but race conditions are still a problem in multi-threaded or forked environments. You can call bottle.db.save() or botle.db.database_name.save() to flush the thread-local memory cache to disk, but there is no way to detect database changes made in other threads until these threads call bottle.db.save() or leave the current request cycle.

Example

from bottle import route, db
@route('/db/counter')
def db_counter():
    if 'hits' not in db.counter:
        db.counter.hits = 0
    db['counter']['hits'] += 1
    return "Total hits: %d!" % db.counter.hits