Made with Supabase

:electric_plug: Streamlit Supabase Connector

Downloads

A Streamlit connection component to connect Streamlit to Supabase Storage and Database.

:thinking: Why use this?

  • Cache functionality to cache returned results. Save time and money on your API requests

  • Same method names as the Supabase Python API. Minimum relearning required

  • Built on top of storage-py and exposes more methods than currently supported by the Supabase Python API. For example, update(), create_signed_upload_url(), and upload_to_signed_url()

  • Less keystrokes required when integrating with your Streamlit app.

    details close summaryExamples with and without the connector /summary br table tr tdbWithout connector/b/tdtdbWith connector/b/td tr td colspan="2" Download file from Supabase storage /td tr td valign="top"

    import mimetypes
    import streamlit as st
    from supabase import create_client
    
    supabase_client = create_client(
        supabase_url="...", supabase_key="..."
    )
    
    bucket_id = st.text_input("Enter the bucket_id")
    source_path = st.text_input("Enter source path")
    
    file_name = source_path.split("/")[-1]
    
    if st.button("Request download"):
        with open(file_name, "wb+") as f:
            response = supabase_client.storage.from_(bucket_id).download(source_path)
            f.write(response)
    
        mime = mimetypes.guess_type(file_name)[0]
        data = open(file_name, "rb")
    
        st.download_button("Download file", data=data, file_name=file_name, mime=mime)
    

    /td td valign="top"

    import streamlit as st
    from st_supabase_connection import SupabaseConnection
    
    st_supabase_client = st.experimental_connection(
        name="supabase_connection", type=SupabaseConnection
    )
    
    bucket_id = st.text_input("Enter the bucket_id")
    source_path = st.text_input("Enter source path")
    
    if st.button("Request download"):
        file_name, mime, data = st_supabase_client.download(bucket_id, source_path)
    
        st.download_button("Download file", data=data, file_name=file_name, mime=mime)
    

    /td tr td colspan="2" Upload file to Supabase storage /td tr td valign="top"

    import streamlit as st
    from supabase import create_client
    
    supabase_client = create_client(
      supabase_key="...", supabase_url="..."
    )
    
    bucket_id = st.text_input("Enter the bucket_id")
    uploaded_file = st.file_uploader("Choose a file")
    destination_path = st.text_input("Enter destination path")
    
    with open(uploaded_file.name, "wb") as f:
        f.write(uploaded_file.getbuffer())
    
    if st.button("Upload"):
        with open(uploaded_file.name, "rb") as f:
            supabase_client.storage.from_(bucket_id).upload(
                path=destination_path,
                file=f,
                file_options={"content-type": uploaded_file.type},
            )
    

    /td td valign="top"

    import streamlit as st
    from st_supabase_connection import SupabaseConnection
    
    st_supabase_client = st.experimental_connection(
        name="supabase_connection", type=SupabaseConnection
    )
    
    bucket_id = st.text_input("Enter the bucket_id")
    uploaded_file = st.file_uploader("Choose a file"):
    destination_path = st.text_input("Enter destination path")
    
    if st.button("Upload"):
        st_supabase_client.upload(bucket_id, uploaded_file, destination_path)
    

    tr /table

    /details

:computer: Demo app

Open in Streamlit

:construction: Setup

  1. Install st-supabase-connection
pip install st-supabase-connection
  1. Set the SUPABASE_URL and SUPABASE_KEY Streamlit secrets as described here.

[!NOTE]
For local development outside Streamlit, you can also set these as your environment variables (recommended), or pass these to the url and key args of st.experimental_connection() (not recommended).

:pen: Usage

  1. Import
from st_supabase_connection import SupabaseConnection
  1. Initialize
st_supabase_client = st.experimental_connection(
    name="YOUR_CONNECTION_NAME",
    type=SupabaseConnection,
    ttl=None,
    url="YOUR_SUPABASE_URL", # not needed if provided as a streamlit secret
    key="YOUR_SUPABASE_KEY", # not needed if provided as a streamlit secret
)
  1. Use in your app to query tables and files. Happy Streamlit-ing! :balloon:

:writing_hand: Examples

:package: Storage operations

List existing buckets

 st_supabase.list_buckets(ttl=None)
[
    SyncBucket(
        id="bucket1",
        name="bucket1",
        owner="",
        public=False,
        created_at=datetime.datetime(2023, 7, 31, 19, 56, 21, 518438, tzinfo=tzutc()),
        updated_at=datetime.datetime(2023, 7, 31, 19, 56, 21, 518438, tzinfo=tzutc()),
        file_size_limit=None,
        allowed_mime_types=None,
    ),
    SyncBucket(
        id="bucket2",
        name="bucket2",
        owner="",
        public=True,
        created_at=datetime.datetime(2023, 7, 31, 19, 56, 28, 203536, tzinfo=tzutc()),
        updated_at=datetime.datetime(2023, 7, 31, 19, 56, 28, 203536, tzinfo=tzutc()),
        file_size_limit=100,
        allowed_mime_types=["image/jpg", "image/png"],
    ),
]

Create a bucket

 st_supabase_client.create_bucket("new_bucket")
{'name': 'new_bucket'}

Update a bucket

 st_supabase_client.update_bucket(
      "new_bucket",
      file_size_limit=100,
      allowed_mime_types=["image/jpg", "image/png"],
      public=True,
    )
{'message': 'Successfully updated'}

Move files in a bucket

 st_supabase_client.move("new_bucket", "test.png", "folder1/new_test.png")
{'message': 'Successfully moved'}

List objects in a bucket

 st_supabase_client.list_objects("new_bucket", path="folder1", ttl=0)
[
    {
        "name": "new_test.png",
        "id": "e506920e-2834-440e-85f1-1d5476927582",
        "updated_at": "2023-08-02T19:53:22.53986+00:00",
        "created_at": "2023-08-02T19:52:20.404391+00:00",
        "last_accessed_at": "2023-08-02T19:53:21.833+00:00",
        "metadata": {
            "eTag": '"814a0034f5549e957ee61360d87457e5"',
            "size": 473831,
            "mimetype": "image/png",
            "cacheControl": "max-age=3600",
            "lastModified": "2023-08-02T19:53:23.000Z",
            "contentLength": 473831,
            "httpStatusCode": 200,
        },
    }
]

Delete a bucket

 st_supabase_client.delete_bucket("new_bucket")
{'message': 'Successfully deleted'}

:file_cabinet: Database operations

Simple query

 st_supabase.query("*", table="countries", ttl=0).execute()
APIResponse(
    data=[
        {"id": 1, "name": "Afghanistan"},
        {"id": 2, "name": "Albania"},
        {"id": 3, "name": "Algeria"},
    ],
    count=None,
)

Query with join

 st_supabase.query("name, teams(name)", table="users",  count="exact", ttl="1h").execute()
APIResponse(
    data=[
        {"name": "Kiran", "teams": [{"name": "Green"}, {"name": "Blue"}]},
        {"name": "Evan", "teams": [{"name": "Blue"}]},
    ],
    count=None,
)

Filter through foreign tables

 st_supabase.query("name, countries(*)", count="exact", table="cities", ttl=None).eq(
        "countries.name", "Curaçao"
    ).execute()

APIResponse(
    data=[
        {
            "name": "Kralendijk",
            "countries": {
                "id": 2,
                "name": "Curaçao",
                "iso2": "CW",
                "iso3": "CUW",
                "local_name": None,
                "continent": None,
            },
        },
        {"name": "Willemstad", "countries": None},
    ],
    count=2,
)

Insert rows

 st_supabase_client.table("countries").insert(
        [{"name": "Wakanda", "iso2": "WK"}, {"name": "Wadiya", "iso2": "WD"}], count="None"
    ).execute()
APIResponse(
    data=[
        {
            "id": 250,
            "name": "Wakanda",
            "iso2": "WK",
            "iso3": None,
            "local_name": None,
            "continent": None,
        },
        {
            "id": 251,
            "name": "Wadiya",
            "iso2": "WD",
            "iso3": None,
            "local_name": None,
            "continent": None,
        },
    ],
    count=None,
)

[!NOTE]
Check the Supabase Python API reference for more examples.

:star: Explore all options in a Streamlit app

Open in Streamlit

:bow: Acknowledgements

This connector builds upon the awesome work done by the open-source community in general and the Supabase Community in particular. I cannot be more thankful to all the authors whose work I have used either directly or indirectly.

Related Projects


A project by Zernonia