Links
📑

Data storage

Databutton provides storage out of the box.
Whether your data comes in tabular form, nested dictionaries, or files, Databutton provides a neat way for you to read and write them through a push / get interface.

Uploading files

If you have data in a file that you want upload to Databutton, click the "New data" button in the sidebar.
.csv files will be converted to a dataframe during uploading, while .json files will become available as Python dictionaries. Text-based files such as .txt, .html, .md will be uploaded as plain text and be available in code as python str. Other files will be treated as raw binary and uploaded as is, available in code as python bytes.

Creating a new dataframe

To create a new or replace an existing dataframe use the following API from any view or job:
import databutton as db
import pandas as pd
# This can be data scraped from API, input from a form,
# or anything else that fits in a dataframe.
data_to_store = []
df = pd.DataFrame(data=data_to_store)
# Save the dataframe 'df' to the key 'my-dataframe',
# making it accessible in your views, jobs, and web UI
db.storage.dataframes.put("my-dataframe", df)

Reading from a dataframe

To access a dataframes in a job or view, Databutton provides the following API:
import databutton as db
# Returns the dataframe stored under 'my-dataframe' or
# an empty dataframe if it does not exist.
df = db.storage.dataframes.get(key="my-dataframe")
By using db.storage.dataframes.get(key), you can access your dataframes anywhere.

Deleting a dataframe

import databutton as db
# deletes the dataframe with the given key
df = db.storage.dataframes.delete(key="my-dataframe")
This will delete the whole dataframe, also its entry in the Data Storage.

Adding records to a dataframe

In order to add new records to a dataframe, e.g. in a scraping job, you could do the following:
import databutton as db
import pandas as pd
# Fetch existing dataframe 'my-dataframe', or if it does
# not exist call the 'default' argument to produce the default value.
# Here we default to returning an empty dataframe.
existing_df = db.storage.dataframes.get(
key="my-dataframe", default=lambda: pd.DataFrame()
)
# Data to add to the dataframe. Could be scraped from an API of your choice.
data = [{"x": 10, "y": 5}]
new_df = pd.DataFrame(data)
# Concatinate the two dataframes
df_to_store = pd.concat([existing_df, new_df], ignore_index=True)
# Store the dataframe safely in Databutton
db.storage.dataframes.put(key="my-dataframe", value=df_to_store)

Working with json files

Use json files to work with nested dict-like structures for smaller and unstructured data. An example use case is taking basic form data input in a view:
import databutton as db
import streamlit as st
config = db.storage.json.get(
"config",
default=lambda: {"email":"[email protected]"}
)
# Use streamlit form
with st.form("my-form"):
email = st.text_input("Email", placeholder=config.get("email", ""))
if st.form_submit_button("Submit"):
# Define a dict with configuration to store as json
config = {"email": email}
# Replace existing config
db.storage.json.put("config", config)
# Show in view that config has been safely stored
st.write("Notification email has been changed!")

Working with text files

Text files are simply fetched as Python strings. If you need to pass it to a library expecting a text file you can wrap the str in io.TextIO like this:
import databutton as db
import streamlit as st
# Get some html page from somewhere
scraped_html = """
Some <b>very</b> interesting content.
"""
# Store it as text in your data app
db.storage.text.put("webpage.html", scraped_html)
# Later retrieve it from databutton storage
html = db.storage.text.get("webpage.html")
# Display using streamlit
st.write(html, unsafe_allow_html=True)

Working with pickle

Pickle files works out of the box with db.storage.binary, here's an example
import databutton as db
import streamlit as st
import pickle
random_object = {1: 2, 3: 4, "foo": "bar"}
st.write(random_object)
pickled = pickle.dumps(random_object)
db.storage.binary.put("pickled-obj", pickled)
stored_obj = db.storage.binary.get("pickled-obj")
unpickled = pickle.loads(stored_obj)
st.write(unpickled)

Working with any other type of file

A file of a type unknown to Databutton can still be stored as a binary file, and fetched as a Python bytes object. If you need to pass it to a library expecting a file as input or output you can wrap the bytes in io.BytesIO like in this basic image processing example using pillow:
import io
import databutton as db
import requests
import streamlit as st
from PIL import Image
# Get image from URL
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
# Apply some image processing
image = image.rotate(45)
# Save image to in-memory bytes buffer
image_buffer = io.BytesIO()
image.save(image_buffer, format="jpeg")
# Put it to databutton storage
image_buffer.seek(0)
db.storage.binary.put("img.jpeg", image_buffer.read())
# Read it back from databutton storage
image_bytes = db.storage.binary.get("img.jpeg")
image = Image.open(io.BytesIO(image_bytes))
# Display image using streamlit
st.image(image)