Web apps in pure Python with reactive components and automatic frontend generation.
—
File uploads, testing framework, middleware system, admin dashboard, data visualization, and experimental features for building sophisticated web applications with enterprise-grade capabilities.
Comprehensive file upload handling with progress tracking, validation, storage management, and security features for robust file processing.
def upload(
*children,
id: str = "",
multiple: bool = False,
accept: list[str] = None,
max_files: int = 1,
max_file_size: int = 100 * 1024 * 1024, # 100MB
disabled: bool = False,
**props
) -> Component:
"""
File upload component with drag-and-drop support and validation.
Provides comprehensive file upload interface with progress tracking,
validation, and integration with backend file processing.
Args:
*children: Upload area content (dropzone, buttons, etc.)
id: Unique identifier for upload session
multiple: Whether to allow multiple file selection
accept: List of accepted file types (MIME types or extensions)
max_files: Maximum number of files allowed
max_file_size: Maximum file size in bytes per file
disabled: Whether upload is currently disabled
**props: Additional component styling and configuration
Returns:
File upload component with drag-and-drop functionality
"""
...
class UploadFile:
"""
Uploaded file representation with metadata and processing utilities.
Represents a file uploaded through the Reflex upload system with
complete metadata, validation results, and storage utilities.
"""
filename: str
"""Original filename from client."""
content_type: str
"""MIME type of the uploaded file."""
size: int
"""File size in bytes."""
file: BinaryIO
"""File-like object for reading content."""
upload_id: str
"""Unique identifier for this upload session."""
def read(self, size: int = -1) -> bytes:
"""
Read file content with optional size limit.
Args:
size: Number of bytes to read (-1 for all)
Returns:
File content as bytes
"""
...
def save(self, path: str) -> None:
"""
Save file to specified filesystem path.
Args:
path: Target filesystem path for saving
"""
...
def validate(self, rules: dict) -> dict:
"""
Validate file against specified rules.
Args:
rules: Validation rules (size, type, etc.)
Returns:
Dictionary with validation results
"""
...
# Upload utility functions
def get_upload_dir() -> str:
"""
Get configured upload directory path.
Returns:
Absolute path to upload directory
"""
...
def get_upload_url(filename: str, upload_id: str = "") -> str:
"""
Get URL for accessing uploaded file.
Args:
filename: Name of uploaded file
upload_id: Upload session identifier
Returns:
URL for accessing the uploaded file
"""
...
def selected_files(upload_id: str = "") -> list[str]:
"""
Get list of selected files for upload session.
Args:
upload_id: Upload session identifier
Returns:
List of selected filenames
"""
...
def clear_selected_files(upload_id: str = "") -> EventHandler:
"""
Clear selected files from upload session.
Args:
upload_id: Upload session to clear
Returns:
EventHandler that clears selected files
"""
...
def cancel_upload(upload_id: str = "") -> EventHandler:
"""
Cancel ongoing file upload operation.
Args:
upload_id: Upload session to cancel
Returns:
EventHandler that cancels upload
"""
...File upload usage example:
class FileUploadState(rx.State):
uploaded_files: list[str] = []
async def handle_upload(self, files: list[rx.UploadFile]):
for file in files:
# Validate file
if file.size > 10 * 1024 * 1024: # 10MB limit
continue
# Save file
upload_path = f"./uploads/{file.filename}"
file.save(upload_path)
self.uploaded_files.append(file.filename)
def file_upload_demo():
return rx.vstack(
rx.upload(
rx.vstack(
rx.button("Select Files", color_scheme="blue"),
rx.text("Or drag and drop files here"),
align="center",
spacing="2"
),
id="file-upload",
multiple=True,
accept=[".pdf", ".jpg", ".png", ".doc"],
max_files=5,
max_file_size=10 * 1024 * 1024,
on_upload=FileUploadState.handle_upload
),
rx.foreach(
FileUploadState.uploaded_files,
lambda filename: rx.text(f"Uploaded: {filename}")
)
)Request/response processing middleware for authentication, logging, CORS, rate limiting, and custom request handling.
def middleware(func: Callable) -> Callable:
"""
Decorator for creating middleware functions.
Middleware functions process requests and responses, enabling
cross-cutting concerns like authentication, logging, and validation.
Args:
func: Function to convert to middleware
Returns:
Middleware function that processes requests/responses
"""
...
class Middleware:
"""
Base middleware class for request processing.
Provides hooks for request preprocessing, response postprocessing,
and error handling in the request lifecycle.
"""
def __init__(self, **config) -> None:
"""
Initialize middleware with configuration.
Args:
**config: Middleware-specific configuration options
"""
...
async def preprocess(self, request: Request) -> Request | Response:
"""
Process request before it reaches route handler.
Args:
request: Incoming HTTP request
Returns:
Modified request or early response
"""
...
async def postprocess(self, request: Request, response: Response) -> Response:
"""
Process response before sending to client.
Args:
request: Original HTTP request
response: Response from route handler
Returns:
Modified response
"""
...
async def on_error(self, request: Request, error: Exception) -> Response:
"""
Handle errors that occur during request processing.
Args:
request: HTTP request that caused error
error: Exception that occurred
Returns:
Error response to send to client
"""
...Middleware examples:
# Authentication middleware
@rx.middleware
async def auth_middleware(request: Request, call_next):
# Check for authentication token
token = request.headers.get("Authorization")
if not token and request.url.path.startswith("/api/protected"):
return Response({"error": "Authentication required"}, status_code=401)
response = await call_next(request)
return response
# Logging middleware
@rx.middleware
async def logging_middleware(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
duration = time.time() - start_time
print(f"{request.method} {request.url.path} - {response.status_code} - {duration:.3f}s")
return response
# CORS middleware
@rx.middleware
async def cors_middleware(request: Request, call_next):
response = await call_next(request)
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE"
response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"
return responseComprehensive testing utilities for component testing, state management validation, and end-to-end application testing.
# Testing module - accessible as rx.testing
import reflex.testing as testing
class TestClient:
"""
Test client for simulating HTTP requests and testing routes.
Provides utilities for testing Reflex applications including
state management, component rendering, and API endpoints.
"""
def __init__(self, app: App) -> None:
"""
Initialize test client with Reflex app.
Args:
app: Reflex application instance to test
"""
...
def get(self, path: str, **kwargs) -> TestResponse:
"""
Simulate GET request to application route.
Args:
path: Route path to request
**kwargs: Additional request parameters
Returns:
Test response with status, content, and metadata
"""
...
def post(self, path: str, data: dict = None, **kwargs) -> TestResponse:
"""
Simulate POST request with data.
Args:
path: Route path for POST request
data: Request payload data
**kwargs: Additional request parameters
Returns:
Test response from POST request
"""
...
def trigger_event(self, event_name: str, payload: dict = None) -> None:
"""
Trigger state event for testing event handlers.
Args:
event_name: Name of event to trigger
payload: Event payload data
"""
...
class ComponentTester:
"""
Utilities for testing individual components and their behavior.
"""
@staticmethod
def render(component: Component) -> dict:
"""
Render component to testable representation.
Args:
component: Component instance to render
Returns:
Dictionary representation of rendered component
"""
...
@staticmethod
def find_by_text(rendered: dict, text: str) -> dict | None:
"""
Find component containing specific text.
Args:
rendered: Rendered component representation
text: Text content to search for
Returns:
Component containing text or None
"""
...
@staticmethod
def find_by_id(rendered: dict, id: str) -> dict | None:
"""
Find component by ID attribute.
Args:
rendered: Rendered component representation
id: Component ID to search for
Returns:
Component with matching ID or None
"""
...
class StateTester:
"""
Utilities for testing state management and event handlers.
"""
@staticmethod
def create_state(state_class: type[State], **initial) -> State:
"""
Create state instance for testing.
Args:
state_class: State class to instantiate
**initial: Initial state values
Returns:
State instance with test configuration
"""
...
@staticmethod
def trigger_event(state: State, method: str, *args, **kwargs) -> dict:
"""
Trigger state method and return resulting state changes.
Args:
state: State instance to test
method: Method name to trigger
*args: Method arguments
**kwargs: Method keyword arguments
Returns:
Dictionary of state changes from event
"""
...Testing examples:
import pytest
import reflex as rx
# Component testing
def test_button_component():
button = rx.button("Click me", on_click=lambda: None)
rendered = rx.testing.ComponentTester.render(button)
assert rendered["tag"] == "Button"
assert "Click me" in rendered["children"]
# State testing
def test_counter_state():
state = rx.testing.StateTester.create_state(CounterState, count=0)
# Test increment
changes = rx.testing.StateTester.trigger_event(state, "increment")
assert changes["count"] == 1
# Test decrement
changes = rx.testing.StateTester.trigger_event(state, "decrement")
assert changes["count"] == 0
# Integration testing
def test_app_routes():
app = rx.App()
client = rx.testing.TestClient(app)
response = client.get("/")
assert response.status_code == 200
response = client.post("/api/data", data={"key": "value"})
assert response.status_code == 201Built-in admin interface for managing database models, monitoring application metrics, and performing administrative tasks.
class AdminDash:
"""
Admin dashboard configuration and management.
Provides web-based admin interface for managing database models,
monitoring application performance, and administrative tasks.
"""
def __init__(
self,
models: list[type[Model]] = None,
path: str = "/admin",
title: str = "Admin Dashboard"
) -> None:
"""
Initialize admin dashboard with model configuration.
Args:
models: List of database models to include in admin
path: URL path for admin interface
title: Dashboard title and branding
"""
...
def add_model(self, model: type[Model], **config) -> None:
"""
Add database model to admin interface.
Args:
model: Model class to add
**config: Model-specific admin configuration
"""
...
def add_view(self, path: str, component: Component, **config) -> None:
"""
Add custom admin view.
Args:
path: URL path for custom view
component: Component to render for view
**config: View configuration options
"""
...
def configure_permissions(self, rules: dict) -> None:
"""
Configure admin access permissions.
Args:
rules: Permission rules for admin access
"""
...Admin dashboard usage:
# Configure admin dashboard
admin = rx.AdminDash(
models=[User, Post, Tag],
path="/admin",
title="My App Admin"
)
# Add to application
app = rx.App()
admin.register(app)
# Custom admin views
@admin.view("/stats", title="Statistics")
def admin_stats():
return rx.vstack(
rx.heading("Application Statistics"),
rx.stat_group(
rx.stat(label="Total Users", value=User.count()),
rx.stat(label="Total Posts", value=Post.count()),
)
)Integration with popular charting libraries for data visualization including Plotly, Recharts, and custom chart components.
def plotly(*children, figure: dict = None, **props) -> Component:
"""
Plotly chart integration for interactive data visualization.
Renders Plotly charts with full interactivity, zoom, pan,
and export capabilities for sophisticated data visualization.
Args:
*children: Chart content (usually empty for Plotly)
figure: Plotly figure dictionary with data and layout
**props: Chart configuration and styling options
Returns:
Interactive Plotly chart component
"""
...
def data_table(
data: list[dict] = None,
columns: list[dict] = None,
pagination: bool = True,
search: bool = True,
sort: bool = True,
**props
) -> Component:
"""
Advanced data table with GridJS integration.
Provides feature-rich data table with sorting, filtering,
pagination, and export capabilities for large datasets.
Args:
data: List of row data as dictionaries
columns: Column configuration with headers and formatting
pagination: Whether to enable pagination
search: Whether to enable search functionality
sort: Whether to enable column sorting
**props: Table styling and configuration options
Returns:
Advanced data table component with interactive features
"""
...
def data_editor(
data: list[dict] = None,
columns: list[dict] = None,
editable: bool = True,
**props
) -> Component:
"""
Interactive data grid editor for spreadsheet-like data editing.
Args:
data: Grid data as list of row dictionaries
columns: Column definitions with types and formatting
editable: Whether cells can be edited inline
**props: Grid configuration and styling
Returns:
Interactive data grid editor component
"""
...
class data_editor_theme:
"""Theme configuration for data editor component."""
def __init__(
self,
accent_color: str = "blue",
font_family: str = "system-ui",
**kwargs
) -> None:
"""
Configure data editor theme.
Args:
accent_color: Primary theme color
font_family: Font family for grid text
**kwargs: Additional theme options
"""
...Data visualization examples:
# Plotly chart
def sales_chart():
figure = {
"data": [
{
"x": ["Jan", "Feb", "Mar", "Apr", "May"],
"y": [20, 14, 23, 25, 22],
"type": "scatter",
"mode": "lines+markers",
"name": "Sales"
}
],
"layout": {
"title": "Monthly Sales",
"xaxis": {"title": "Month"},
"yaxis": {"title": "Sales ($1000)"}
}
}
return rx.plotly(figure=figure)
# Data table
def user_table():
return rx.data_table(
data=[
{"name": "John", "email": "john@example.com", "age": 30},
{"name": "Jane", "email": "jane@example.com", "age": 25},
],
columns=[
{"field": "name", "header": "Name", "sortable": True},
{"field": "email", "header": "Email"},
{"field": "age", "header": "Age", "type": "number"}
],
pagination=True,
search=True
)Specialized components for enhanced user experience including notifications, content rendering, and interactive elements.
def toast(*children, **props) -> Component:
"""
Toast notification system with multiple variants and positioning.
Provides non-intrusive notifications with automatic dismissal,
action buttons, and consistent positioning across the application.
Args:
*children: Toast content (text, icons, buttons)
**props: Toast configuration (variant, position, duration)
Returns:
Toast notification component
"""
...
def markdown(content: str, **props) -> Component:
"""
Markdown content rendering with syntax highlighting.
Renders Markdown content with support for code blocks,
tables, links, and custom styling integration.
Args:
content: Markdown content string to render
**props: Markdown renderer configuration
Returns:
Rendered Markdown content component
"""
...
def code_block(
code: str = "",
language: str = "python",
theme: str = "default",
**props
) -> Component:
"""
Syntax-highlighted code block for documentation and examples.
Args:
code: Source code content to display
language: Programming language for syntax highlighting
theme: Color theme for syntax highlighting
**props: Code block styling options
Returns:
Syntax-highlighted code block component
"""
...
def logo(**props) -> Component:
"""
Reflex logo component for branding and attribution.
Args:
**props: Logo styling and sizing options
Returns:
Reflex logo component
"""
...class FileManagerState(rx.State):
files: list[dict] = []
upload_progress: dict = {}
async def handle_upload(self, files: list[rx.UploadFile]):
for file in files:
# Validate file
if not self.validate_file(file):
continue
# Process file
processed_file = {
"name": file.filename,
"size": file.size,
"type": file.content_type,
"url": rx.get_upload_url(file.filename),
"uploaded_at": datetime.now()
}
self.files.append(processed_file)
def validate_file(self, file: rx.UploadFile) -> bool:
# Size validation (10MB limit)
if file.size > 10 * 1024 * 1024:
return False
# Type validation
allowed_types = ["image/jpeg", "image/png", "application/pdf"]
return file.content_type in allowed_types
def file_manager():
return rx.vstack(
rx.upload(
rx.card(
rx.vstack(
rx.icon("upload"),
rx.text("Drop files here or click to upload"),
rx.text("Max 10MB per file", size="sm", color="gray"),
align="center",
spacing="2"
),
variant="surface"
),
multiple=True,
accept=[".jpg", ".png", ".pdf"],
on_upload=FileManagerState.handle_upload
),
rx.foreach(
FileManagerState.files,
lambda file: rx.card(
rx.hstack(
rx.text(file["name"]),
rx.spacer(),
rx.text(f"{file['size']} bytes", size="sm"),
align="center"
)
)
)
)import pytest
import reflex as rx
@pytest.fixture
def app():
return rx.App()
@pytest.fixture
def client(app):
return rx.testing.TestClient(app)
def test_user_registration(client):
# Test user registration flow
response = client.post("/api/register", data={
"username": "testuser",
"email": "test@example.com",
"password": "secure123"
})
assert response.status_code == 201
assert response.json()["username"] == "testuser"
def test_state_persistence():
# Test state management
state = rx.testing.StateTester.create_state(UserState)
# Test login
changes = rx.testing.StateTester.trigger_event(
state, "login", "testuser", "secure123"
)
assert changes["is_logged_in"] == True
assert changes["username"] == "testuser"from typing import Any, Dict, List, Optional, Union, BinaryIO, Callable
from datetime import datetime
# File Upload Types
FileContent = BinaryIO # File content stream
FileMetadata = Dict[str, Any] # File metadata dictionary
UploadConfig = Dict[str, Any] # Upload configuration
# Middleware Types
MiddlewareFunc = Callable[[Any], Any] # Middleware function
RequestHandler = Callable # Request handler function
ResponseHandler = Callable # Response handler function
# Testing Types
TestResponse = Any # HTTP test response
ComponentRender = Dict[str, Any] # Rendered component representation
StateChanges = Dict[str, Any] # State change dictionary
# Admin Types
ModelConfig = Dict[str, Any] # Admin model configuration
AdminView = Callable[[], Component] # Admin view function
PermissionRule = Dict[str, Any] # Permission configuration
# Chart Types
PlotlyFigure = Dict[str, Any] # Plotly figure dictionary
ChartData = List[Dict[str, Any]] # Chart data as list of records
TableColumn = Dict[str, Any] # Table column configuration
# Notification Types
ToastVariant = Literal["info", "success", "warning", "error"]
ToastPosition = Literal["top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right"]
# Content Types
MarkdownContent = str # Markdown content string
CodeContent = str # Source code content
LanguageIdentifier = str # Programming language nameInstall with Tessl CLI
npx tessl i tessl/pypi-reflex