Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
946c3da
Adding pages
elnelson575 Sep 24, 2025
626a355
Updates so far
elnelson575 Sep 24, 2025
431e43f
Updates
elnelson575 Sep 24, 2025
a8b519d
Updates
elnelson575 Sep 25, 2025
0e0aaba
additional updates
elnelson575 Sep 26, 2025
da8dbc5
Current draft
elnelson575 Sep 29, 2025
699424e
Current
elnelson575 Sep 29, 2025
266ab00
Updates after chat
elnelson575 Sep 30, 2025
9dd6968
Updates
elnelson575 Sep 30, 2025
4805903
Notes plus remove old modules
elnelson575 Sep 30, 2025
c17f67e
More updates
elnelson575 Sep 30, 2025
4049b1f
Updates made
elnelson575 Oct 1, 2025
e95251d
Updated with apps
elnelson575 Oct 2, 2025
55dd234
Overhaul reading data
cpsievert Oct 3, 2025
4cb680e
Updates to persistent storage
elnelson575 Oct 6, 2025
35e1e90
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 6, 2025
1c5e67f
Updated content
elnelson575 Oct 14, 2025
c0fb77a
additional context
elnelson575 Oct 14, 2025
5495740
Progress
elnelson575 Oct 16, 2025
69b5748
both ibis examples added
elnelson575 Oct 16, 2025
84ef625
More updates
elnelson575 Oct 16, 2025
71f6b76
Updates
elnelson575 Oct 16, 2025
8fcdfe1
Connect info
elnelson575 Oct 16, 2025
0a7074b
Added link
elnelson575 Oct 16, 2025
8b72ab7
Switching order
elnelson575 Oct 16, 2025
d94ff03
Correction
elnelson575 Oct 16, 2025
ed4d240
Added notif
elnelson575 Oct 16, 2025
7316570
Simplified
elnelson575 Oct 16, 2025
0d24fe7
wip updates to persistent data article
cpsievert Oct 17, 2025
fe6aa14
Added reading from remote
elnelson575 Oct 17, 2025
236b9d4
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 17, 2025
85c129a
finish brain dump on persistent data
cpsievert Oct 17, 2025
9d8dc96
Remove link in Essentials section
cpsievert Oct 17, 2025
f56a135
Small edits
elnelson575 Oct 17, 2025
ee9a24d
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 17, 2025
bf16744
Corrections to first example
elnelson575 Oct 20, 2025
ae744ed
Corrected GoogleSheets example
elnelson575 Oct 20, 2025
0029cb7
Smoothed out the string/boolean thing
elnelson575 Oct 20, 2025
a71285b
Restoring paste error in setup for sheets
elnelson575 Oct 20, 2025
44ad71c
Removed try except at start
elnelson575 Oct 20, 2025
51e3f27
Updates to dotenv
elnelson575 Oct 20, 2025
ea0e918
Update docs/reading-data.qmd
elnelson575 Oct 20, 2025
5eba31e
Minor updates to wording
elnelson575 Oct 20, 2025
905e4ac
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 20, 2025
8ac4e62
small changes/improvements
cpsievert Oct 20, 2025
a9ea13c
QA on code up to cloud store
elnelson575 Oct 20, 2025
e0b73ed
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 20, 2025
26d9a3e
More corrections to reading data
elnelson575 Oct 20, 2025
e357af0
More correcdtions to reaction section
elnelson575 Oct 20, 2025
00cc639
Final corrections for ibis
elnelson575 Oct 20, 2025
4656336
small changes/improvements
cpsievert Oct 20, 2025
6e59994
Update docs/persistent-storage.qmd
cpsievert Oct 20, 2025
67e0ca4
Updating s3
elnelson575 Oct 21, 2025
ca6c439
Merge branch 'feat/new-data-docs' of https://github.com/posit-dev/py-…
elnelson575 Oct 21, 2025
099a8b8
Moving some examples to separate app folder, add screenshot
elnelson575 Oct 24, 2025
16eeed2
Changing examples
elnelson575 Oct 24, 2025
f29f527
Minor grammar edits to reading data
elnelson575 Oct 24, 2025
4726423
Minor grammar edits for persistent storage
elnelson575 Oct 24, 2025
d335f64
Updating template pages
elnelson575 Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions docs/persistent-storage.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
title: Persistent storage & writing data
editor:
markdown:
wrap: sentence
lightbox:
effect: fade
---

## Intro

## When do you actually need persistent storage
* You want your application to collect and save information from your users. Example, forms.
* You need to save a result that your users generate? (ex. save a copy of report generated)

Note: What are we not talking about here: Auth. Link to any auth docs we have.

CALLOUT: Connect does both Auth and supports secrets for storage. Link to those docs.

## Saving to the filesystem?
Cover best practices with saving to shared servers/spaces?
Ex. Saving to a shared drive from a local server?

### Example with pins and polars? (use a form, save the result)

TODO: Update this
```python
from shiny import App, Inputs, Outputs, Session, ui, reactive, render
import pandas as pd

app_ui = ui.page_fluid(
ui.h2("Submitted Results"),
ui.output_data_frame("results_df"),
ui.input_text("text", "Enter text", value=""),
ui.input_checkbox("checkbox", "I like checkboxes"),
ui.input_slider("slider", "My favorite number is:", min=0, max=100, value=50),
ui.input_action_button("submit", "Submit"),
)


def server(input: Inputs, output: Outputs, session: Session):
df = reactive.value(pd.DataFrame(columns=["text", "checkbox", "slider"]))

@reactive.effect
@reactive.event(input.submit)
def results():
row = {
"text": input.text(),
"checkbox": input.checkbox(),
"slider": input.slider(),
}
row_df = pd.DataFrame([row])
new_df = pd.concat([df.get(), row_df], ignore_index=True)
df.set(new_df)

@render.data_frame
def results_df():
return render.DataGrid(df.get())


app = App(app_ui, server)
```


### Example with DuckDB (use a form, save the result)

#### DuckDB
```python
from shiny import App, Inputs, Outputs, Session, ui, reactive, render
import duckdb

con = duckdb.connect("test_db.db")

app_ui = ui.page_fluid(
ui.h2("Submitted Results"),
ui.output_data_frame("results_df"),
ui.input_text("text", "Enter text", value=""),
ui.input_checkbox("checkbox", "I like checkboxes"),
ui.input_slider("slider", "My favorite number is:", min=0, max=100, value=50),
ui.input_action_button("submit", "Submit"),
)

def server(input: Inputs, output: Outputs, session: Session):
# Initialize a reactive value so we start with the table visible.
df = reactive.value(con.sql("SELECT * FROM data").df())

@reactive.effect
@reactive.event(input.submit)
def save():
row = [input.text(), input.checkbox(), input.slider()]

# We use a prepared statement here to avoid SQL injection
con.execute("INSERT INTO data VALUES (?, ?, ?)", row)
con.commit()

# Set the reactive value so the table updates
df.set(con.sql("SELECT * FROM data").df())

@render.data_frame
def results_df():
return df()


app = App(app_ui, server, debug=True)
```
## Connecting to databases

### Example connecting with Ibis and saving to db with a form

### SQL injection prevention

### Connection pooling & transaction locking?

### Note on credentials? (don't use your admin creds in your app, have user creds for db, scope them narrowly, etc.)



### Example Applications
::: {.panel-tabset .panel-pills}

#### Polars


#### DuckDB
Outliers app: Reads and writes from DuckDB https://github.com/skaltman/outliers-app-db-python/blob/main/app.py
Database Explorer: https://shiny.posit.co/py/templates/database-explorer/

#### Pandas
AWS-Community-Builders-App: Process data from a CSV and displays it https://github.com/robertgv/aws-community-builders-dashboard

#### Sqlite3
Database monitoring app: https://github.com/posit-dev/py-shiny-templates/tree/main/monitor-database




Loading
Loading