Server logic
In Shiny, the server logic is defined within a function which takes three arguments: input
, output
, and session
. It looks something like this:
def server(input, output, session):
# Server code goes here
...
All of the server logic we’ll discuss, such as using inputs and define outputs, happens within the server function.
Each time a user connects to the app, the server function executes once — it does not re-execute each time someone moves a slider or clicks on a checkbox. So how do updates happen? When the server function executes, it creates a number of reactive objects that persist as long as the user stays connected — in other words, as long is their session is active. These reactive objects are containers for functions that automatically re-execute in response to changes in inputs.
Accessing inputs
Input values are accessed via input.x()
, where x
is the name of the input. If you need to access an input by a name that is not known until runtime, you can do that with []
:
= "x"
input_name input[input_name]() # Equivalent to input["x"]() or input.x()
In Python, input.x()
is equivalent to input$x
in Shiny for R. Unlike in R, ()
is necessary to retrieve the value. This aligns the reading of inputs with the reading of reactive values and reactive expressions. It also makes it easier to pass inputs to module server functions.
You can’t read input values at the top level of the server function. If you try to do that, you’ll get an error that says RuntimeError: No current reactive context
. The input values are reactive and, as the error suggests, are only accessible within reactive code. We’ll learn more about that in the upcoming sections.
Defining outputs
To define the logic for an output, create a function with no parameters whose name matches a corresponding output ID in the UI. Then apply a render
decorator and the @output
decorator.
Here’s server function that defines a single text output named txt
. Inside of that output function, it reads the value of input.enable()
.
def server(input, output, session):
@output
@render.text
def txt():
if input.enable():
return "Yes!"
else:
return "No!"
When you define an output function, Shiny makes it reactive, and so it can be used to access input values.
Now we can put together the UI we created earlier with the server function to create an App
object. When we do that, the resulting object must be named app
in order for the application to run.
#| standalone: true
#| components: [editor, viewer]
from shiny import App, render, ui
app_ui = ui.page_fluid(
ui.input_checkbox("enable", "Enable?"),
ui.h3("Is it enabled?"),
ui.output_text_verbatim("txt"),
)
def server(input, output, session):
@output
@render.text
def txt():
if input.enable():
return "Yes!"
else:
return "No!"
app = App(app_ui, server)