🌐 Translations: 🇺🇦 Українська
A lightweight, asynchronous, namespaced storage utility for Flet applications.
FletStorage is a powerful wrapper around Flet's built-in SharedPreferences. It simplifies client-side data persistence by adding automatic JSON serialization, allowing you to store and retrieve complex Python objects without manual conversion, while keeping your data organized and isolated.
- Automatic JSON serialization: Store and retrieve
dict,list,int,bool,str, andsetdirectly without manual conversion. - Namespaced storage: Automatically prefixes keys with
app_nameto prevent data collisions between different applications on the same device. - Asynchronous and parallel: Fully asynchronous API with parallel deletion in the
clear()method for maximum performance. - Robust error handling: Clear
KeyErrorandValueErrorexceptions for predictable data management. - Set support: Python sets are automatically preserved during serialization and deserialization.
pip install flet-storageimport flet as ft
from flet_storage import FletStorage
async def main(page: ft.Page):
# Initialize storage with a unique namespace
storage = FletStorage("my_app")
# Save data
await storage.set("user", {"name": "Ivan", "age": 25})
await storage.set("settings", {"theme": "dark", "language": "en"})
# Retrieve data
user = await storage.get("user")
print(user) # {'name': 'Ivan', 'age': 25}
# Get with default value
config = await storage.get_or_default("config", {"version": "1.0"})
print(config) # {'version': '1.0'}
# Check if key exists
exists = await storage.contains_key("user")
print(exists) # True
# Get all keys
keys = await storage.get_keys()
print(keys) # ['user', 'settings']
# Remove a key
await storage.remove("settings")
# Clear entire storage
await storage.clear()
ft.run(main)FletStorage automatically serializes and deserializes the following Python types:
| Type | Description | Example |
|---|---|---|
dict |
Dictionaries | {"key": "value"} |
list |
Lists | [1, 2, 3] |
set |
Sets (preserved) | {"a", "b", "c"} |
str |
Strings | "hello" |
int, float |
Numbers | 42, 3.14 |
bool |
Booleans | True, False |
None |
None value | None |
Sets are automatically preserved during storage and retrieval:
# Storing a set
tags = {"python", "flet", "async"}
await storage.set("tags", tags)
# Retrieving (returns a set, not a list!)
tags = await storage.get("tags")
print(type(tags)) # <class 'set'> ✅
print(tags) # {'python', 'flet', 'async'}
# Sets in nested structures work too
data = {
"user": "Ivan",
"tags": {"web", "mobile"},
"categories": ["tech", "programming"]
}
await storage.set("profile", data)
profile = await storage.get("profile")
# profile["tags"] is a set ✅
# profile["categories"] is a list ✅Technical Note: Sets are stored internally as {"__type__": "set", "values": [...]}. If you need to store a dictionary with a "__type__" key that equals "set", it may be incorrectly interpreted as a set marker during deserialization.
Initializes the storage with a unique namespace.
Parameters:
app_name(str): The unique namespace for the application.
Example:
storage = FletStorage("todo_app")Serializes an object to JSON and stores it under a namespaced key.
Parameters:
key(str): The unique key identifier (without namespace).obj(object): Any JSON-serializable object (dict, list, set, str, int, etc.).
Returns:
bool:Trueif the operation was successful.
Example:
await storage.set("preferences", {"notifications": True})
await storage.set("tags", {"python", "flet"}) # Sets are supported!Retrieves and deserializes an object by its key.
Parameters:
key(str): The key identifier to look up.
Returns:
Any: The deserialized Python object.
Raises:
KeyError: If the key does not exist in the storage.ValueError: If the stored data is not valid JSON.
Example:
try:
data = await storage.get("preferences")
except KeyError:
print("Key not found")Gets the value for the given key or returns a default value if not found.
Parameters:
key(str): The key identifier to look up.default(Any): The value to return if the key does not exist. Defaults toNone.
Returns:
Any: The deserialized object if found, otherwise the default value.
Raises:
ValueError: If the stored data is not valid JSON.
Example:
config = await storage.get_or_default("config", {"version": "1.0"})Checks if a specific key exists within the application namespace.
Parameters:
key(str): The key identifier to check.
Returns:
bool:Trueif the key exists,Falseotherwise.
Example:
if await storage.contains_key("user_token"):
token = await storage.get("user_token")Removes a specific key and its value from the storage.
Parameters:
key(str): The key identifier to remove.
Returns:
bool:Trueif the operation was successful.
Example:
await storage.remove("temp_data")Retrieves all keys belonging to the current application namespace.
Returns:
list[str]: A list of keys with theapp_name.prefix removed.
Example:
all_keys = await storage.get_keys()
print(f"Stored {len(all_keys)} keys")Deletes all keys and values associated with the current application namespace. Other namespaces in SharedPreferences remain untouched.
Example:
await storage.clear() # Removes all app dataasync def save_user_settings(storage: FletStorage, settings: dict):
await storage.set("settings", settings)
print("Settings saved")
async def load_user_settings(storage: FletStorage) -> dict:
return await storage.get_or_default("settings", {
"theme": "light",
"language": "en",
"notifications": True
})async def add_todo(storage: FletStorage, task: str):
todos = await storage.get_or_default("todos", [])
todos.append({"task": task, "completed": False})
await storage.set("todos", todos)
async def get_all_todos(storage: FletStorage) -> list:
return await storage.get_or_default("todos", [])
async def clear_completed_todos(storage: FletStorage):
todos = await storage.get_or_default("todos", [])
active_todos = [t for t in todos if not t["completed"]]
await storage.set("todos", active_todos)async def add_tag(storage: FletStorage, tag: str):
tags = await storage.get_or_default("tags", set())
tags.add(tag)
await storage.set("tags", tags)
async def remove_tag(storage: FletStorage, tag: str):
tags = await storage.get_or_default("tags", set())
tags.discard(tag)
await storage.set("tags", tags)
async def get_all_tags(storage: FletStorage) -> set:
return await storage.get_or_default("tags", set())import time
async def cache_data(storage: FletStorage, key: str, data: Any, ttl: int = 3600):
cache_entry = {
"data": data,
"expires_at": time.time() + ttl
}
await storage.set(f"cache_{key}", cache_entry)
async def get_cached_data(storage: FletStorage, key: str) -> Any | None:
try:
cache_entry = await storage.get(f"cache_{key}")
if time.time() < cache_entry["expires_at"]:
return cache_entry["data"]
else:
await storage.remove(f"cache_{key}")
return None
except KeyError:
return Noneasync def safe_get_data(storage: FletStorage, key: str):
try:
data = await storage.get(key)
return data
except KeyError:
print(f"Key '{key}' not found")
return None
except ValueError as e:
print(f"JSON error: {e}")
return None-
Use descriptive namespace names: Choose a unique
app_nameto avoid conflicts with other applications. -
Handle exceptions: Always handle
KeyErrorandValueErrorwhen working withget(). -
Use
get_or_default(): For optional data, this is more convenient than exception handling. -
Structure your data: Store related data together in dictionaries for better organization.
-
Clean up stale data: Regularly remove unnecessary keys to keep storage clean.
-
Use sets for unique collections: Sets are automatically preserved and are perfect for storing unique items like tags or categories.
This repository contains a specialised skill for AI agents. It helps the agent provide expert assistance in writing Python code and integrating this library into your projects.
To install the skill, run:
npx skills add https://github.com/BogdanovychA/flet-storage --skill flet-storageMIT License
Contributions are welcome! Please submit pull requests on GitHub.
If you encounter any issues or have questions:
- Open an issue on GitHub
Made with ❤️ for the Flet community