You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm building Django sites for several of my graduate MSBA classes. Being able to incorporate Shiny apps for GenAI chat, ML, etc. would be so much easier—at least for me—than having to use Vue or React. To make that work well, however, I need to maintain student state as they complete exercises and progress through the class materials.
I tried to use Django's session management system but ran into several challenges:
While I can access Django session state in the Shiny app_ui (via the request object), I cannot access it in the Shiny server function where the app logic and state updates happen.
There’s no built-in way for Shiny for Python to read or write Django session data from within the server function, making it hard to persist user progress or restore state.
I tried workarounds with custom middleware an HTTP calls but was not success. It seems likely that any such solution may insufficiently stable for production or teaching.
It would be incredibly helpful if Shiny for Python could natively support reading and writing session state from ASGI-compatible frameworks (like Django, FastAPI, or Starlette) inside the server function, so user state (e.g., student progress through the course) can be managed easily. This would benefit not just Django users, but anyone integrating Shiny with modern Python web frameworks.
I'd be happy to provide a cleaned up version of that I have been working on if that would be useful.
Thank you for considering this!
Solution
Allow Shiny for Python apps to access and modify the session state from the parent ASGI framework (e.g., FastAPI, Starlette, Django) directly within the Shiny server function.
How it should work:
When a Shiny app is mounted within an ASGI app (such as FastAPI or Starlette), the session or user state from the parent app should be accessible in both app_ui and server.
The Shiny server function should receive a session object that allows reading and writing to the parent ASGI session (e.g., for user progress, preferences, authentication, etc.).
State changes in Shiny should be persisted back to the parent ASGI session automatically.
Ideally, the session parameter in the Shiny server function would be an object (e.g., SessionASGI) that exposes the parent ASGI session dict, so we can read and write session data as needed.
Shiny for Python could achieve this by looking for a session object in the ASGI scope (such as scope["session"], which is set by common ASGI session middleware in FastAPI, Starlette, or Django). If found, Shiny would pass this object to the server function, allowing seamless integration with the parent app’s session management.
Example (with FastAPI):
fromfastapiimportFastAPI, Requestfromfastapi.responsesimportRedirectResponsefromstarlette.middleware.sessionsimportSessionMiddlewarefromshinyimportApp, ui, renderimportuvicornimportwebbrowser# from shiny import SessionASGI # (if implemented)app=FastAPI()
app.add_middleware(SessionMiddleware, secret_key="mysecret")
@app.get("/set-user")asyncdefset_user(request: Request):
request.session["user_name"] ="Alice"returnRedirectResponse("/shiny")
defapp_ui(request: Request):
# Access session in UI (already possible)user_name=request.session.get("user_name", "Guest")
returnui.page_fluid(
ui.h2(f"Welcome, {user_name}!"),
ui.input_text("answer", "Your answer:"),
ui.output_text_verbatim("feedback"),
)
defserver(input, output, session): # would be ..., session: SessionASGI# NEW: Access and update FastAPI/Starlette session directlyuser_name=session["user_name"] # Read from ASGI session@output@render.textdeffeedback():
# Save answer to sessionsession["answer"] =input.answer()
returnf"Thanks, {user_name}! Your answer was saved."defsave_progress():
# Save the latest answer to the ASGI sessionsession["last_answer"] =input.answer()
# Optionally, do other cleanup or loggingsession.on_ended(save_progress)
shiny_app=App(app_ui, server)
app.mount("/shiny", shiny_app)
if__name__=="__main__":
host="127.0.0.1"port=8000# Open the /set-user URL in the default browserwebbrowser.open(f"http://{host}:{port}/set-user")
# Start the serveruvicorn.run(app, host=host, port=port, log_level="info")
Contribution? (Optional)
Yes, I can review/test.
The text was updated successfully, but these errors were encountered:
Ideally, the session parameter in the Shiny server function would be an object (e.g., SessionASGI) that exposes the parent ASGI session dict, so we can read and write session data as needed.
Being session specific is the difficult part.
I'm answering under the guise of a non-expert of Starlette...
I don't see a way to have directly sharable session context between the different routes via https://www.starlette.io/routing/ . I see the ability to enhance the request and response, but nothing about the app as a whole.
One way out is through cookies. This could be utilized by an independent FastAPI as well as Shiny. But within each sub-app, you'd need to handle populating the session's info. Within py-shiny, I'd recommend not storing any cross-sub-app data and instead ask the database each time. (You could cache it within the session, but you'll need a cache-invalidation mechanism. 🤞 )
You'd be able to access the request.session in the app_ui's request object. Within the server, my best guess is to look within session.http_conn (untested).
Leaving the issue as need-triage until a better pair of eyes looks. (But I'm currently not hopeful for a clean solution outside of Starlette's SessionMiddleware middlware)
I'm building Django sites for several of my graduate MSBA classes. Being able to incorporate Shiny apps for GenAI chat, ML, etc. would be so much easier—at least for me—than having to use Vue or React. To make that work well, however, I need to maintain student state as they complete exercises and progress through the class materials.
I tried to use Django's session management system but ran into several challenges:
It would be incredibly helpful if Shiny for Python could natively support reading and writing session state from ASGI-compatible frameworks (like Django, FastAPI, or Starlette) inside the server function, so user state (e.g., student progress through the course) can be managed easily. This would benefit not just Django users, but anyone integrating Shiny with modern Python web frameworks.
I'd be happy to provide a cleaned up version of that I have been working on if that would be useful.
Thank you for considering this!
Solution
Allow Shiny for Python apps to access and modify the session state from the parent ASGI framework (e.g., FastAPI, Starlette, Django) directly within the Shiny server function.
How it should work:
Ideally, the session parameter in the Shiny server function would be an object (e.g., SessionASGI) that exposes the parent ASGI session dict, so we can read and write session data as needed.
Shiny for Python could achieve this by looking for a session object in the ASGI scope (such as scope["session"], which is set by common ASGI session middleware in FastAPI, Starlette, or Django). If found, Shiny would pass this object to the server function, allowing seamless integration with the parent app’s session management.
Example (with FastAPI):
Contribution? (Optional)
Yes, I can review/test.
The text was updated successfully, but these errors were encountered: