Datastar Python SDK

repository·develop·Indexed 41 days ago

https://github.com/starfederation/datastar-python

A Python SDK (datastar-py v1.0.2) for Datastar, enabling backend developers to interact with Datastar's SSE-based frontend. It provides helpers for generating SSE events via ServerSentEventGenerator, reading frontend signals, and creating framework-specific responses for Django, FastAPI, FastHTML, Litestar, Quart, Sanic, and Starlette. Includes an attribute_generator for type-checked data-* HTML attributes, supporting bindings, event listeners, and visibility controls.

Tokens
10.9K
Snippets
46
Records
50
Agent score
51%

What's inside Datastar Python

  1. Overview of Datastar Python SDK

    develop

    The datastar-py package is a Python SDK for Datastar, a framework that uses Server-Sent Events (SSE) to send responses from the backend to the browser.

    Key capabilities include:

    • Generating SSE events (patching elements or signals).
    • Creating framework-specific response helpers (Django, FastAPI, FastHTML, Litestar, Quart, Sanic, and Starlette).
    • Reading the current state of frontend signals via read_signals.
    • Generating data-* HTML attributes with type checking and IDE completion.

    Framework-specific helpers are located in sub-packages, such as datastar_py.quart or datastar_py.fastapi.

  2. Run Datastar Python examples with uv

    develop

    Most examples in this repository use PEP 723 Inline Script Metadata, which allows you to run them using uv without manually managing a virtual environment or installing dependencies first.

    To run an example, navigate to its directory and use uv run <script-name>.

    # Example for FastAPI
    cd examples/fastapi && uv run app.py
    
    # Example for Fasthtml
    cd examples/fasthtml && uv run simple.py
    
    # Example for Sanic
    cd examples/sanic && uv run app.py
  3. Handle long-lived streams in Sanic

    develop

    Sanic handles long-lived SSE streams differently than other supported frameworks. Instead of passing a generator to DatastarResponse, you use a helper to get a response object and then call .send() on it within a loop.

    from datastar_py import ServerSentEventGenerator as SSE
    # Replace 'sanic' with your framework
    from datastar_py.sanic import datastar_respond
    
    @app.get("/updates")
    async def updates(request):
        response = await datastar_respond(request)
        while True:
            await response.send(SSE.patch_elements("<div id='mydiv'></div>"))
            await asyncio.sleep(1)
  4. Run Datastar with Django using ASGI (Recommended)

    develop

    For full Datastar capabilities, use an ASGI server. The example uses daphne to provide an ASGI-compatible runserver.

    To run the demo:

    1. Install the project dependencies.
    2. Start the server using the built-in ASGI runserver provided by Daphne.
    3. Access the demo at http://127.0.0.1:8000/.
    # No specific command provided in source, but implies standard dependency installation and running the ASGI server
  5. Run Datastar Python examples with pip

    develop

    If you are not using uv, you can run the examples using a standard Python virtual environment. You must manually install the dependencies listed in the # dependencies = [...] metadata comment at the top of each example script.

    1. Create and activate a virtual environment.
    2. Install datastar-py and any other dependencies listed in the script's metadata.
    3. Run the script.
    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    pip install datastar-py <other-dependencies-from-script>
    python <script-name>
  6. Use the AttributeGenerator to create Datastar attributes

    develop

    The attribute_generator (an instance of AttributeGenerator) is the primary entry point for creating HTML attributes used by Datastar. It handles the serialization of Python values into JavaScript expressions and manages the data- prefix (or a custom alias).

    Common patterns include:

    • Signals: Patching state into the frontend using .signals().
    • Bindings: Two-way data binding with .bind() or text binding with .text().
    • Events: Handling user or browser events with .on().
    • Visibility: Toggling elements with .show().
    • Styles/Classes: Syncing CSS classes or inline styles with signals.
    from datastar_py.attributes import attribute_generator
    
    # Example: Creating a set of attributes for an input element
    # This would result in: data-bind="name" data-on-input="console.log(name)"
    attrs = attribute_generator.bind("name").on("input", "console.log(name")
    print(attrs)
  7. Read frontend signals with read_signals

    develop

    Datastar includes the current state of frontend signals in every request. The read_signals helper allows you to retrieve these signals as a dictionary in your backend handler.

    Usage varies slightly by framework, but typically requires passing the request object.

    from datastar_py.quart import read_signals
    
    @app.route("/updates")
    async def updates():
        signals = await read_signals()
        # signals is a dictionary of the current frontend state
  8. Use Response Helpers to return Datastar events

    develop

    Datastar responses can contain zero to many events. The SDK provides DatastarResponse classes for each supported framework to wrap these events correctly.

    Note: You must import DatastarResponse from the package corresponding to your framework (e.g., from datastar_py.fastapi import DatastarResponse).

    Common patterns:

    • Zero events: Returns a 204 status.
    • Single event: Pass a single SSE event.
    • Multiple events: Pass a list of SSE events.
    • Long-lived streams: Pass an async generator to DatastarResponse (supported by all frameworks except Sanic).
    from datastar_py import ServerSentEventGenerator as SSE
    # Replace 'fastapi' with your framework
    from datastar_py.fastapi import DatastarResponse
    
    # 0 events, a 204
    @app.get("zero")
    def zero_event():
        return DatastarResponse()
    
    # 1 event
    @app.get("one")
    def one_event():
        return DatastarResponse(SSE.patch_elements("<div id='mydiv'></div>"))
    
    # 2 events
    @app.get("two")
    def two_event():
        return DatastarResponse([
            SSE.patch_elements("<div id='mydiv'></div>"),
            SSE.patch_signals({"mysignal": "myval"}),
        ])
    
    # N events, a long lived stream
    @app.get("/updates")
    async def updates():
        async def _():
            while True:
                yield SSE.patch_elements("<div id='mydiv'></div>")
                await asyncio.sleep(1)
        return DatastarResponse(_())
  9. Use the @datastar_response decorator

    develop

    The @datastar_response decorator simplifies returning Datastar responses by automatically wrapping the function's return value in a DatastarResponse. It supports sync functions, async functions, and generator functions.

    When using a generator, the decorator allows you to yield SSE events directly from your route handler without needing to wrap the generator in a separate response object. You should apply this decorator under your framework's routing decorator.

    from datastar_py.sanic import datastar_response, ServerSentEventGenerator as SSE
    
    @app.get('/my_route')
    @datastar_response
    async def my_route(request):
        while True:
            yield SSE.patch_elements("<div id='mydiv'></div>")
            await asyncio.sleep(1)
  10. Generate Datastar HTML attributes

    develop

    The attribute_generator (aliased as data) helps generate data-* attributes for HTML. This provides IDE completion and type checking when using various HTML generation libraries (like FastHTML, htpy, or f-strings).

    If you are using a custom prefix for Datastar attributes, you can instantiate AttributeGenerator manually.

    from datastar_py import attribute_generator as data
    
    # Using with f-strings
    f"<button {data.on('click', 'console.log(\'clicked\')').debounce(1000).stop()}>My Button</button>"
    
    # Using a custom alias
    from datastar_py.attributes import AttributeGenerator
    data = AttributeGenerator(alias="data-star-")
    # This will generate attributes like data-star-on