render_quak
render_quak class
Reactively render a quak data table.
Usage Source
render_quak(
_fn: Optional[ValueFn[ValueT]] = None,
*,
width: Optional[str] = None,
height: Optional[str] = None,
fill: Optional[bool] = None,
fillable: Optional[bool] = None,
rate_policy: Optional[RatePolicy] = None,
rate_delay: Optional[float] = None,
allow_unrestricted_connection: bool = False,
)@render_quak is a decorator that creates a render function – a function that returns the table to display and re-runs when the reactive values it reads change:
import pandas as pd
from shinywidgets import render_quak
df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
@render_quak
def table():
return dfThe render function may return either a DataFrame-like object (e.g., a pandas or polars DataFrame, or a pyarrow Table), which is coerced to a quak.Widget (requires pip install 'shinywidgets[quak]'), or a quak.Widget. In a filling layout, the table grows to fit its container.
Note
Accessing the rendered widget: the render function gains two read-only attributes: .value, the value it most recently returned, and .widget, the rendered quak.Widget instance. Widget state can also be read reactively with .read("some_trait") (a shortcut for reactive_read() on .widget).
Responding to user interaction: read the table’s accessors in a reactive function (a @render.* function, @reactive.calc, or @reactive.effect), which re-runs whenever the user sorts or brushes, much like input.my_slider():
table.sql(): the SQL query for the table’s current sort and filter state.table.data(): the matching rows, as a lazy DuckDB relation.
They can’t be read inside this output’s own render function, which builds a new table each time it runs. For anything beyond them, use table.read() (a shortcut for reactive_read() on table.widget).
Mutating the widget: use .widget to update the rendered table in place; trait changes on the widget are synced to the browser.
Security: like render_embedding_atlas, quak runs its queries by sending SQL from the browser to the widget’s DuckDB connection, so without restrictions any visitor can send arbitrary SQL, including SQL that reads or writes files on the server. The renderer locks down the widget’s connection before display (SET enable_external_access = false; SET lock_configuration = true); pass allow_unrestricted_connection=True to opt out (e.g., a local, single-user app). A connection whose configuration is already locked is left untouched (its owner took control of its settings). If you build the quak.Widget yourself from a DuckDB connection (quak.Widget(con)), the widget uses that connection directly, and DuckDB’s lockdown is permanent (it can’t be undone) and database-wide, so the first render locks it for every other use in the process: do any server-side file reads on it before the first render, or pass allow_unrestricted_connection=True for it.
Even with the lockdown, a visitor can still send expensive queries, which block the Python process while they run.
Parameters
allow_unrestricted_connection : bool = False-
When
True, the widget’s DuckDB connection is left as the render function returned it, without the lockdown described above. The default (False) is strongly recommended for deployed apps: an unrestricted connection lets any visitor run arbitrary SQL with the server process’s permissions. width : Optional[str] = None-
A CSS length unit (e.g.,
"400px"or"100%") for the output’s width. height : Optional[str] = None-
A CSS length unit for the output’s height. When
None(the default), the output is designed to fill the height of its parent container (seefillandfillable). fill : Optional[bool] = None-
Whether the output should grow or shrink to fit its parent container. When
None(the default), this isTrueifheightis not specified. fillable : Optional[bool] = None-
Whether the output container should fill available space (scrolling its contents on overflow). When
None(the default), this isTrueifheightis not specified. rate_policy : Optional[RatePolicy] = None-
How to rate-limit
sql()(debounced by default) andreactive_read()on the widget:"debounce"or"throttle".None(the default) keeps the debounce, and debouncesreactive_read()only ifrate_delayis given. rate_delay : Optional[float] = None-
The rate-limit window in seconds (default 0.25).
0disables rate limiting. Each :which :
See also
output_widget(): in Shiny Core, the UI needs this to hold the output (Shiny Express displays it where the render function is defined).
Methods
data() |
The rows matching the current sort and filter, as a lazy DuckDB relation (materialize it with .df(), .pl(), or .aggregate(...)). |
sql() |
The SQL query for the table’s current sort and filter state (a str). |
data()
render_quak.data()The rows matching the current sort and filter, as a lazy DuckDB relation (materialize it with .df(), .pl(), or .aggregate(...)).
Re-reads whenever sql() changes and runs the query on each read, so prefer calling it once inside a @reactive.calc and sharing the result over calling it in several outputs. Runs the published query that sql() returns, so the two always describe the same state (even inside the debounce window).
sql()
render_quak.sql()The SQL query for the table’s current sort and filter state (a str).
Brush quak’s column histograms or sort a column and this query updates, debounced (250 ms) by default – see the rate_policy and rate_delay parameters. While the table initializes the query is briefly empty, in which case reading this cancels (like reading an output that hasn’t rendered yet), so no req() guard is needed. The query is read-only: setting it from Python doesn’t change the table.