Databases

Bottle (>0.4.6) offers a persistent key/value database accessible through the bottle.db module variable. You can use key or attribute syntax to store or fetch any pickle-able object to the database. Both bottle.db.bucket_name.key_name and bottle.db[bucket_name][key_name] will work.

Missing buckets are created on demand. You don’t have to check for their existence before using them. Just be sure to use alphanumeric bucket-names.

The bucket objects behave like mappings (dictionaries), except that only strings are allowed for keys and values must be pickle-able. Printing a bucket object doesn’t print the keys and values, and the items() and values() methods are not supported. Missing keys will raise KeyError as expected.

Persistence

During a request live-cycle, all changes 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. Each bucket is stored in a separate file in `bottle.DB_PATH`. Be sure to allow write-access to this path and use bucket names that are allowed in filenames.

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.bucket_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