Datasy Object¶
The Datasy class is the central data management object in Flet-Easy that provides access to page data, routing functionality, authentication, and event handling. Every page function receives a Datasy instance as its first parameter.
Overview¶
The Datasy object serves as your main interface for:
- Page Access: Direct access to Flet's Page object
- URL Parameters: Extract dynamic route parameters
- Navigation: Advanced routing and navigation methods
- Authentication: Login/logout functionality with JWT support
- Data Sharing: Session-based data sharing between pages
- Event Handling: Keyboard and resize event management
- View Management: Access to configured view templates
Core Properties¶
page¶
- Type:
ft.Page - Description: Direct access to the Flet Page object
@app.page("/example")
def example_page(data: fs.Datasy):
# Access page properties
data.page.title = "My Page Title"
data.page.window_width = 800
data.page.window_height = 600
data.page.update()
url_params¶
- Type:
Dict[str, Any] - Description: Dictionary containing URL route parameters
@app.page("/user/{id:int}/profile/{tab:str}")
def user_profile(data: fs.Datasy, id: int, tab: str):
# Access via function parameters (recommended)
user_id = id
active_tab = tab
# Or via url_params dictionary
user_id = data.url_params["id"]
active_tab = data.url_params["tab"]
view¶
- Type:
fs.Viewsy - Description: Access to the configured global view template
@app.page("/example")
def example_page(data: fs.Datasy):
# Modify the global view
data.view.appbar.title = ft.Text("New Title")
data.view.appbar.bgcolor = ft.Colors.RED
return ft.View(
controls=[ft.Text("Content")],
appbar=data.view.appbar,
drawer=data.view.drawer
)
Route Properties¶
# Access route configuration
data.route_prefix # App route prefix
data.route_init # Initial route
data.route_login # Login redirect route
data.route # Current route path
Navigation Methods¶
go (route)¶
Navigate to a specific route.
@app.page("/home")
def home_page(data: fs.Datasy):
return ft.View(
controls=[
ft.ElevatedButton(
"Go to Profile",
on_click=data.go("/profile")
),
ft.ElevatedButton(
"Go to Settings",
on_click=data.go("/settings")
),
# Using lambda for event handlers
ft.ElevatedButton(
"Go to About",
on_click=lambda _: data.go("/about")
)
]
)
go_back()¶
âš¡ Enhanced in v0.3.0
Navigate to the previous route in history. Now executes directly without returning a lambda function.
@app.page("/details")
def details_page(data: fs.Datasy):
def handle_back(_):
# v0.3.0: Executes immediately
data.go_back()
return ft.View(
controls=[
ft.Text("Details Page"),
ft.ElevatedButton("Go Back", on_click=handle_back),
# Or use lambda wrapper for event handling
ft.ElevatedButton("Back (Lambda)", on_click=lambda _: data.go_back())
]
)
go_navigation_bar (e)¶
New in v0.3.0
Handle navigation bar changes for ft.NavigationBar or ft.CupertinoNavigationBar. This method automatically navigates to the page with the corresponding index parameter.
# Define pages with index parameters
@app.page("/home", title="Home", index=0)
def home_page(data: fs.Datasy):
return ft.View(
controls=[ft.Text("Home Page")],
navigation_bar=data.view.navigation_bar
)
@app.page("/search", title="Search", index=1)
def search_page(data: fs.Datasy):
return ft.View(
controls=[ft.Text("Search Page")],
navigation_bar=data.view.navigation_bar
)
# Configure global navigation bar
@app.view
def main_view(data: fs.Datasy):
return fs.Viewsy(
navigation_bar=ft.NavigationBar(
destinations=[
ft.NavigationBarDestination(icon=ft.Icons.HOME, label="Home"),
ft.NavigationBarDestination(icon=ft.Icons.SEARCH, label="Search"),
],
on_change=data.go_navigation_bar # Direct method reference
)
)
go_route (route)¶
New in v0.3.0
Navigate to a specific route immediately (executes directly, unlike data.go() which returns a lambda function).
@app.page("/dashboard")
def dashboard_page(data: fs.Datasy):
def handle_quick_nav(_):
# Direct navigation - executes immediately
data.go_route("/settings")
return ft.View(
controls=[
ft.Text("Dashboard"),
ft.ElevatedButton("Quick Settings", on_click=handle_quick_nav),
# Compare with lambda approach
ft.ElevatedButton("Lambda Settings", on_click=data.go("/settings"))
]
)
redirect (route)¶
Enhanced in v0.3.0
Redirect to a specific route immediately. This method is executed directly, and importantly, it is now available not just for middlewares, but also directly in page functions to force a quick redirection.
@app.page("/old-route")
def old_page(data: fs.Datasy):
# Determine if we should redirect automatically instead of rendering
if not user_has_feature_enabled():
# Executes directly and prevents rendering the current view
return data.redirect("/new-route")
return ft.View(
controls=[ft.Text("Old Route Content")]
)
page_reload()¶
New in v0.3.0
Reload the current page and restore default values. This method is particularly useful for resetting page state and stopping ongoing processes.
Use Cases:
- Reset form fields to default values
- Stop running counters or timers
- Clear temporary page state
- Refresh dynamic content
import flet as ft
import flet_easy as fs
import time
app = fs.FletEasy(route_init="/counter")
@app.page(route="/counter", title="Counter")
def counter_page(data: fs.Datasy):
page = data.page
txt_number = ft.TextField(value="0", text_align="right", width=100)
play = False
def add_numbers(e):
nonlocal play
if not play:
# Long running process
play = True
for i in range(100):
txt_number.value = str(int(txt_number.value) + 1)
time.sleep(1)
page.update()
def reload_page(e):
# Reset everything to default state
data.page_reload()
return ft.View(
controls=[
ft.Row([
ft.IconButton(
ft.Icons.REPLAY_OUTLINED,
on_click=reload_page,
tooltip="Reset Page"
),
txt_number,
ft.IconButton(
ft.Icons.PLAY_ARROW,
on_click=add_numbers,
tooltip="Start Counter"
),
], alignment="center"),
],
vertical_alignment="center",
horizontal_alignment="center",
)
app.run()
🎬 Demo¶
dynamic_control(control, func_update)¶
New in v0.3.0
Add dynamic control updates for cached pages. Allows real-time updates when caching is enabled.
@app.page("/live-data", cache=True)
def live_data_page(data: fs.Datasy):
# Dynamic appbar title updates
def update_title(appbar):
current_time = datetime.now().strftime("%H:%M:%S")
appbar.title = ft.Text(f"Live Data - {current_time}")
data.page.update()
# Register dynamic control
data.dynamic_control(data.view.appbar, update_title)
# Dynamic content updates
content_text = ft.Text("Loading...")
def update_content(text_control):
text_control.value = f"Updated at {datetime.now()}"
data.page.update()
data.dynamic_control(content_text, update_content)
return ft.View(
controls=[
content_text,
ft.ElevatedButton(
"Refresh",
on_click=lambda _: data.page_reload()
)
],
appbar=data.view.appbar
)
history_routes¶
- Type:
deque[Tuple[str, int]] - Description: Get navigation history as a deque of (route, timestamp) tuples
@app.page("/debug")
def debug_page(data: fs.Datasy):
history = data.history_routes
history_text = "\n".join([f"{route} at {timestamp}" for route, timestamp in history])
return ft.View(
controls=[
ft.Text("Navigation History:"),
ft.Text(history_text),
]
)
Authentication Methods¶
login(key, value, next_route)¶
Store authentication data in client storage.
@app.page("/login")
def login_page(data: fs.Datasy):
username_field = ft.TextField(label="Username")
password_field = ft.TextField(label="Password", password=True)
def handle_login(_):
username = username_field.value
password = password_field.value
# Validate credentials (your logic here)
if authenticate_user(username, password):
# Store authentication token
data.login("auth_token", username, next_route='/dashboard')
else:
data.page.show_snack_bar(
ft.SnackBar(content=ft.Text("Invalid credentials"))
)
return ft.View(
controls=[
ft.Text("Login", size=24),
username_field,
password_field,
ft.ElevatedButton("Login", on_click=handle_login)
]
)
logout(key, next_route)¶
âš¡ Enhanced in v0.3.0
Closes the sessions of all browser tabs or the device used, which has been previously configured with the login method. Now executes directly without returning a lambda function.
Parameters:
key(str): The storage key to remove from client storagenext_route(str, optional): Route to navigate to after logout. Defaults toroute_loginif not specified.
@app.page("/dashboard", protected_route=True)
def dashboard_page(data: fs.Datasy):
def handle_logout(_):
# v0.3.0: Executes immediately and redirects
data.logout('auth_token', next_route='/other-route')
return ft.View(
controls=[
ft.Text("Welcome to Dashboard"),
ft.ElevatedButton("Logout", on_click=handle_logout)
ft.ElevatedButton("Quick Logout", on_click=lambda _: data.logout('auth_token'))
]
)
Data Sharing System¶
The share property provides enhanced session storage with additional methods.
Basic Usage¶
@app.page("/page1", share_data=True)
def page1(data: fs.Datasy):
def save_data(_):
# Store shared data
data.share.set("user_preferences", {
"theme": "dark",
"language": "en"
})
data.share.set("cart_items", ["item1", "item2", "item3"])
data.go("/page2")
return ft.View(
controls=[
ft.Text("Page 1 - Set Data"),
ft.ElevatedButton("Save & Go to Page 2", on_click=save_data)
]
)
@app.page("/page2", share_data=True)
def page2(data: fs.Datasy):
# Retrieve shared data
preferences = data.share.get("user_preferences")
cart_items = data.share.get("cart_items")
return ft.View(
controls=[
ft.Text("Page 2 - Retrieved Data"),
ft.Text(f"Theme: {preferences.get('theme') if preferences else 'None'}"),
ft.Text(f"Cart Items: {len(cart_items) if cart_items else 0}"),
]
)
Enhanced Methods¶
@app.page("/data-manager", share_data=True)
def data_manager_page(data: fs.Datasy):
# Check if shared data exists
has_data = data.share.contains()
# Get all shared values as a list
all_values = data.share.get_values()
# Get complete shared data dictionary
all_data = data.share.get_all()
return ft.View(
controls=[
ft.Text(f"Has shared data: {has_data}"),
ft.Text(f"Number of values: {len(all_values)}"),
ft.Text(f"All keys: {list(all_data.keys())}"),
]
)
Event Handling¶
Keyboard Events¶
@app.page("/keyboard-demo")
def keyboard_demo(data: fs.Datasy):
output_text = ft.Text("Press any key...")
# Add keyboard event handler
def handle_keyboard():
key_info = data.on_keyboard_event.test() # Get all key info
key = data.on_keyboard_event.key()
shift = data.on_keyboard_event.shift()
ctrl = data.on_keyboard_event.ctrl()
alt = data.on_keyboard_event.alt()
meta = data.on_keyboard_event.meta()
output_text.value = f"Key: {key}, Shift: {shift}, Ctrl: {ctrl}, Alt: {alt}, Meta: {meta}"
data.page.update()
# Register the handler
data.on_keyboard_event.add_control(handle_keyboard)
return ft.View(
controls=[
ft.Text("Keyboard Event Demo"),
output_text,
]
)
Resize Events¶
@app.page("/resize-demo")
def resize_demo(data: fs.Datasy):
size_text = ft.Text("Resize the window...")
def handle_resize():
width = data.on_resize.width()
height = data.on_resize.height()
size_text.value = f"Window size: {width}x{height}"
data.page.update()
# Register resize handler
data.on_resize.add_control(handle_resize)
return ft.View(
controls=[
ft.Text("Resize Event Demo"),
size_text,
]
)
The Datasy object is your primary interface for building interactive Flet-Easy applications. Master these methods and properties to create powerful, responsive applications with excellent user experience.