Storage
Introduction
Browsers have various mechanisms to store data. localStorage
and IndexedDB
are two such mechanisms. These are particularly useful for storing data offline.
The anvil_extras storage
module provides wrappers around both these storage mechanisms in a convenient dictionary like API.
In order to store data you’ll need a store object. You can import the default store objects local_storage
or indexed_db
.
Alternatively create your own store object using the classmethod create_store(store_name)
.
NB: when working in the IDE the app is running in an IFrame and the storage objects may not be available. This can be fixed by changing your browser settings. Turning the shields down in Brave or making sure not to block third party cookies in Chrome should fix this.
Which to chose?
local_storage
.bytes
) - use indexed_db
.datetime
and date
objects are also supported.
If you want to store anything else you’ll need to convert it to something JSONable first.
Usage Examples
Store user preference
from anvil_extras.storage import local_storage
class UserPreferences(UserPreferencesTemplate):
def __init__(self, **properties):
self.init_components(**properties)
def dark_mode_checkbox_change(self, **event_args):
local_storage['dark_mode'] = self.dark_mode_checkbox.checked
Change the theme at startup
## inside a startup module
from anvil_extras.storage import local_storage
if local_storage.get('dark_mode') is not None:
# set the app theme to dark
...
Create an offline todo app
from anvil_extras.storage import indexed_db
from anvil_extras.uuid import uuid4
todo_store = indexed_db.create_store('todos')
# create_store() is a classmethod that takes a store_name
# it will create another store object inside the browsers IndexedDB
# or return the store object if it already exists
# the todo_store acts as dictionary like object
class TodoPage(TodoPageTemplate):
def __init__(self, **properties):
self.init_components(**properties)
self.todo_panel.items = list(todo_store.values())
def save_todo_btn_click(self, **event_args):
if not self.todo_input.text:
return
id = str(uuid4())
todo = {"id": id, "todo": self.todo_input.text, "completed": False}
todo_store[id] = todo
self.todo_panel.items = self.todo_panel.items + [todo]
self.todo_input.text = ""
API
- class StorageWrapper
- class IndexedDBWrapper
- class LocalStorageWrapper
both
indexed_db
andlocal_storage
are instances of the dictionary like classesIndexedDBWrapper
andLocalStorageWrapper
respectively.- classmethod create_store(name)
Create a store object. e.g.
todo_store = indexed_db.create_store('todos')
. This will create a new store inside the browser’sIndexedDB
and return anIndexedDBWrapper
instance. Theindexed_db
object is equivalent toindexed_db.create_store('default')
. To explore this further, open up devtools and findIndexedDB
in the Application tab. Sincecreate_store
is a classmethod you can also dotodo_store = IndexedDBWrapper.create_store('todos')
.
- is_available()
Check if the storage object is supported. Returns a
boolean
.
- list(store)
Return a list of all the keys used in the store.
- len(store)
Return the number of items in store.
- store[key]
Return the value of store with key key. Raises a
KeyError
if key is not in store.
- store[key] = value
Set
store[key]
to value. If the value is not a JSONable data type it may be stored incorrectly. If storingbytes
objects it is best to use theindexed_db
store.datetime
anddate
objects are also supported.
- del store[key]
Remove
store[key]
from store.
- key in store
Return
True
if store has a key key, elseFalse
.
- iter(store)
Return an iterator over the keys of the store. This is a shortcut for
iter(store.keys())
.
- clear()
Remove all items from the store.
- get(key[, default])
Return the value for key if key is in store, else default. If default is not given, it defaults to
None
, so that this method never raises aKeyError
.
- items()
Return an iterator of the store’s
(key, value)
pairs.
- keys()
Return an iterator of the store’s keys.
- pop(key[, default])
If key is in store, remove it and return its value, else return default. If default is not given, it defaults to
None
, so that this method never raises aKeyError
.
- store(key, value)
Equivalent to
store[key] = value
.
- update([other])
Update the store with the key/value pairs from other, overwriting existing keys. Return
None
.update()
accepts either a dictionary object or an iterable of key/value pairs (as tuples or other iterables of length two). If keyword arguments are specified, store is then updated with those key/value pairs:store.update(red=1, blue=2)
.
- values()
Return an iterator of the store’s values.