Accessible resources from webapps#
Web applications need access to various resources to function correctly. These resources can be internal (stored in Dataiku) or external (stored outside of Dataiku).
To access these resources, there are several strategies that developers can use depending on the specific use case. For example, the developer can use a JavaScript function to fetch the necessary data or assets if the resource is required during an event, such as when a button is clicked. Alternatively, the developer can use server-side code to retrieve the necessary information if the resource is needed when the web app is being built, for example. This tutorial will outline some of the most essential best practices for accessing resources in web apps.
At the end of the tutorial the complete code is provided for each framework. Each code highlights all different use cases for one dedicated framework.
External resources#
When creating a web application in Dataiku that requires accessing external resources, the process is similar to traditional web application development. In other words, you can use the standard HTML tags to access a resource on a specific URL. For instance, Code 1 below illustrates how to display an image using an external URL.
<img src="https://picsum.photos/200/300" alt="Random picture from the internet"></img>
Or you can use Javascript to retrieve data.
/* Javascript function for external URL */
let externalImageJs = document.getElementById('externalImageJs')
fetch("https://picsum.photos/200/300")
.then(response => response.blob())
.then(image => externalImageJs.src = URL.createObjectURL(image))
html.Div([html.Div(["You can use images coming from an URL by using the classical ",
html.Code('html.Img(src="URL_TO_USE", alt="Alternate text")')]),
html.Img(src="https://picsum.photos/200/300", alt="Image to display")])),
st.markdown("""## From external URL""")
with st.container():
st.write("### Display an image")
Internal resources#
Web applications in Dataiku can use resources stored in Dataiku. There are various places where resources can be stored.
The section Internal resources stored in a managed folder explains how to use resources stored in a managed folder. Storing data in a managed folder is outside the scope of this tutorial, as there is nothing more than creating a managed folder and putting your data in it. These resources are tied to a project when storing resources in a managed folder. If you need to store resources for multiple project, consider storing them in the Global shared code or sharing the managed folder across projects.
The section Using resources stored in resources in project library explains how to use resources stored in the resources project library. These resources are tied to a project library. So you should consider this option, if your data are local to a project, do not want those data to appear in the flow, and you need the user to have a minimal set of permissions (defined by the project) to access or edit those data.
The section Internal resources stored in the global shared code explains how to store user resources stored in the Static web resources, defined in the Global shared code in the application menu. Suppose your resources are not dedicated to a project and are not sensitive data, or your web application is intended to be a public web app. In that case you should store these resources in the Static web resources.
The section Using resources stored in the Code Studios focuses on Code Studios and its usage when storing resources inside. You should store your resources in Code Studio. If you want your resources been between multiple projects within Code Studio templates, use the “Append to Dockerfile” block; see Preparing Code Studio templates.
The tutorial explains how to handle three different file types in each section. Depending on the framework, file usage can change depending on the file type. We have highlighted the most frequent usage of images, files, and CSS. Even though those resources are handled in the same way, the purpose of their usage changes.
Internal resources stored in a managed folder#
Displaying an image#
There are three steps to follow to load and use an image in a Dataiku web application:
Use the
img
tag in your HTML with thesrc
attribute set to""
(Code 2.1).In the Python backend, create a route to retrieve and serve the image file (Code 2.2).
In the JavaScript tab, dynamically set the image source to the route created in Code 2.2 (Code 2.3)
<img id="getImageFromManageFolderImg" alt="image" class="container"></img>
import dataiku
import pandas as pd
from flask import request
# Definition of the various resources (This can be done programmatically)
# ## Name of the managed folder
folder = "Resources"
# ## Path name of the files
image = "/image.png"
pdf = "/document.pdf"
css = "/my-css.css"
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieve the file from the managed folder
Args:
folder_name: name of the managed folder
file_name: name of the file
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
return (f.read())
@app.route('/get_image_from_managed_folder')
def get_image_from_managed_folder():
return get_file_from_managed_folder(folder, image)
let getImageFromManageFolderImg = document.getElementById('getImageFromManageFolderImg')
getImageFromManageFolderImg.src = getWebAppBackendUrl('/get_image_from_managed_folder')
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input
from dash.dependencies import Output
import dataiku
import base64
import logging
logger = logging.getLogger(__name__)
folder_name = "Resources"
image_name = "/image.png"
pdf_name = "/document.pdf"
css_name = "/my-css.css"
def get_image_from_managed_folder():
""" Read a Png image and return the encoded version
Returns:
a base64 encoded image
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(image_name) as f:
image = f.read()
return 'data:image/png;base64,' + base64.b64encode(image).decode('utf-8')
html.Div([html.Div([
"You can use images coming from a managed folder by using the classical, in conjunction with a python funtion ",
html.Code(
'html.Img(src=function_that_returns_the_image, alt="Alternate text")')]),
html.Img(src=get_image_from_managed_folder(), alt="Image to display",
className="container")])),
import streamlit as st
import dataiku
import io
import logging
logger = logging.getLogger(__name__)
host = "http://<dssURL>:<port>/"
folder = "Resources"
image = "/image.jpg"
pdf = "/file.pdf"
css = "/my-css.css"
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieves a file from a managed folder
:param folder_name: name of the folder to retrieve the file from
:param file_name: name of the file to retrieve
Returns:
the file.
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
st.markdown("""## From managed folder""")
with st.container():
st.write("### Display an image")
Serving a file#
Serving a file for an end-user relies on the same principle. Except you don’t display it.
<p>The image is loaded within the javascript code</p>
<a id="getPDFFromManagedFolderA" href="" download="file.pdf">
<span id="getPDFFromManagedFolder" onclick="" class="btn btn-primary">Get PDF file</span>
</a>
let getPDFFromManagedFolder = document.getElementById('getPDFFromManagedFolder')
let getPDFFromManagedFolderA = document.getElementById('getPDFFromManagedFolderA')
getPDFFromManagedFolderA.href = getWebAppBackendUrl('/get_pdf_from_managed_folder')
getPDFFromManagedFolder.addEventListener('click', () => {
getWebAppBackendUrl('/get_pdf_from_managed_folder')
});
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieve the file from the managed folder
Args:
folder_name: name of the managed folder
file_name: name of the file
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
return (f.read())
@app.route('/get_pdf_from_managed_folder')
def get_pdf_from_managed_folder():
return get_file_from_managed_folder(folder, pdf)
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input
from dash.dependencies import Output
import dataiku
import base64
import logging
logger = logging.getLogger(__name__)
folder_name = "Resources"
image_name = "/image.png"
pdf_name = "/document.pdf"
css_name = "/my-css.css"
# use the style of examples on the Plotly documentation
@app.callback(
Output("downloadManagedFolder", "data"),
Input("btnImageManagedFolder", "n_clicks"),
prevent_initial_call=True,
)
def download_file(_):
"""Serve a file
Args:
_ : not use
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(pdf_name) as f:
file = f.read()
return dcc.send_bytes(file, pdf_name[1:])
html.Div([html.P([
"For downloading a file, you should use the html.Download, and a button to activate the download"]),
html.Button("Get the file", className="btn btn-primary",
id="btnImageManagedFolder"),
dcc.Download(id="downloadManagedFolder")])),
import streamlit as st
import dataiku
import io
import logging
logger = logging.getLogger(__name__)
host = "http://<dssURL>:<port>/"
folder = "Resources"
image = "/image.jpg"
pdf = "/file.pdf"
css = "/my-css.css"
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieves a file from a managed folder
:param folder_name: name of the folder to retrieve the file from
:param file_name: name of the file to retrieve
Returns:
the file.
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
with st.container():
st.write("### Serving a file")
Using your own CSS#
If you need to use your own CSS, apply the same principle as in Serving a file.
<link href="" rel="stylesheet" id="getCSSFromManagedFolder">
<p>The image <span class="devadvocate-alert">is loaded</span> within the javascript code</p>
let getCSSFromManagedFolder = document.getElementById('getCSSFromManagedFolder')
getCSSFromManagedFolder.href = getWebAppBackendUrl('/get_css_from_managed_folder')
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieve the file from the managed folder
Args:
folder_name: name of the managed folder
file_name: name of the file
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
return (f.read())
@app.route('/get_css_from_managed_folder')
def get_css_from_managed_folder():
return get_file_from_managed_folder(folder, css)
You can’t use a defined CSS in a managed folder in a Dash web application.
If you want to use your own CSS, configure the app.config.external_stylesheets
.
You can’t use a defined CSS in a managed folder in a Streamlit web application.
If you want to use your own CSS, use st.markdown
.
For now, streamlit offers very few options for using a custom CSS.
Using resources stored in resources in project library#
If you want to store resources specific to a project, need the user to be authenticated
and do not want to create a managed folder, you can rely on resources stored in the project library.
Go to </> > Libraries and click on the Resources tab. Then create a static
directory.
Once the directory has been created, upload your files in this folder.
All files in this folder will be accessible, by authenticated user,
via the URL: http[s]://host:port/local/projects/PROJECT_KEY/resources/
.
Alternatively, if you want to store project-related resources that are meant to be accessible to any unauthenticated user,
you can create a local-static
directory and upload your files in it.
The files in this folder will be publicly accessible
via the URL: http[s]://host:port/local/projects/PROJECT_KEY/public-resources/
Displaying an image#
<img id="getImageFromProjectLibImg" alt="image" class="container"></img>
let getImageFromProjectLibImg = document.getElementById('getImageFromProjectLibImg')
getImageFromProjectLibImg.src = `/local/projects/${dataiku.defaultProjectKey}/resources/image.jpg`
html.Div([html.Div(
["You use images coming from resources in the project library by using the classical:",
html.Code("""html.Img(src="URLOfTheResources", alt="Alternate text)""")]),
html.Img(
src=f"/local/projects/{dataiku.default_project_key()}/resources/image.jpg"),
])
with st.container():
st.write("### Display an image (using URL)")
st.image(f"{host}/local/projects/{dataiku.api_client().get_default_project().project_key}/resources/image.jpg")
st.write("### Display an image (using the Code studio location)")
with open('../../project-lib-resources/static/image.jpg', 'rb') as f:
Serving a file#
Serving a file for an end-user relies on the same principle. Except you don’t display it.
<p>The pdf link is updated within the javascript code</p>
<a id="getPDFFromProjectLibA" href="" download="file.pdf">
<span id="getPDFFromProjectLib" onclick="" class="btn btn-primary">Get PDF file</span>
</a>
let getPDFFromProjectLibA = document.getElementById('getPDFFromProjectLibA')
getPDFFromProjectLibA.href = `/local/projects/${dataiku.defaultProjectKey}/resources/file.pdf`
html.Div([html.P(
"To be able to use the resources folder in project library, you need to fallback to the usage of the A tag. "),
html.A(children=[
html.Span("Get the PDF", className="btn btn-primary")
], href=f"/local/projects/{dataiku.default_project_key()}/resources/file.pdf",
download="file.pdf")])),
with st.container():
st.write("### Serving a file")
with open('../../project-lib-resources/static/file.pdf', 'rb') as f:
Using your own CSS#
If you need to use your own CSS, apply the same principle as in Serving a file.
<link href="" rel="stylesheet" id="getCSSFromProjectLib">
<p>The image <span class="devadvocate-alert">is loaded</span> within the javascript code</p>
let getCSSFromProjectLib = document.getElementById('getCSSFromProjectLib')
getCSSFromProjectLib.href = `/local/projects/${dataiku.defaultProjectKey}/resources/my-css.css`
You simply need to adapt the app.config.external_stylesheets
to your needs.
app.config.external_stylesheets = ["https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css",
"/local/static/my-css.css",
f"/local/projects/{dataiku.default_project_key()}/resources/my-css.css"
]
You can’t use a defined CSS in a managed folder in a Streamlit web application.
If you want to use your own CSS, use st.markdown
.
For now, streamlit offers very few options for using a custom CSS.
Using resources stored in the Code Studios#
Code Studios does not allow editing Standard, Dash, and Bokeh web applications. Code Studios resources are stored inside the container, so to access a file in the resources, you need to fall back to classical file system operation. Depending on where the user stores its files, they will appear in different directories in Code Studio. Accessing to those files will remain the same regardless of the directory.
Displaying an image#
Not available
Not available
with st.container():
st.write("### Display an image")
with open('../../code_studio-resources/image.jpg', 'rb') as f:
Serving a file#
Serving a file for an end-user relies on the same principle. Except you don’t display it.
Not available
Not available
with st.container():
st.write("### Serving a file")
with open('../../code_studio-resources/file.pdf', 'rb') as f:
Using your own CSS#
If you need to use your own CSS, apply the same principle as in Serving a file.
Not available
Not available
Not available
Complete code and conclusion#
Code 12 shows the complete code for using resources when developing web applications. This tutorial presents best practices for data storage according to your use case.
You will find the complete code for standard web application
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link href="" rel="stylesheet" id="getCSSFromManagedFolder">
<link href="" rel="stylesheet" id="getCSSFromProjectLib">
<h1 class="display-1">Using resources in a web application</h1>
<p>Some code samples to demonstrate how we can use resources in web applications</p>
<div class="container">
<h2 class="" dispaly-2>From external URL</h2>
<div class="accordion" id="externalURL">
<div class="accordion-item">
<h2 class="accordion-header" id="headingExternalURL">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseExternalURL"
aria-expanded="false" aria-controls="collapseExternalURL">
Image
</button>
</h2>
<div id="collapseExternalURL" class="accordion-collapse collapse" aria-labelledby="headingExternalURL"
data-bs-parent="#externalURL">
<div class="accordion-body">
<p>You can use images comming from an URL by using the classical
<code><img scr="URL_TO_USE" alt="Description"/></code>
</p>
<img src="https://picsum.photos/200/300" alt="Random picture from the internet"></img>
</div>
</div>
</div>
</div>
<div class="accordion" id="externalURLJs">
<div class="accordion-item">
<h2 class="accordion-header" id="headingExternalURLJs">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseExternalURLJs"
aria-expanded="false" aria-controls="collapseExternalURLJs">
Fetching resources from javascript
</button>
</h2>
<div id="collapseExternalURLJs" class="accordion-collapse collapse" aria-labelledby="headingExternalURLJs"
data-bs-parent="#externalURLJs">
<div class="accordion-body">
<p>Or you can use Javascript to fetch resources.</p>
<img src="" alt="Random picture from the internet" id="externalImageJs"></img>
</div>
</div>
</div>
</div>
<h2>From managed folders</h2>
<div class="accordion" id="accordion-managed-folder">
<div class="accordion-item">
<h2 class="accordion-header" id="displayInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapsedisplayInline"
aria-expanded="false" aria-controls="collapsedisplayInline">
Display an image
</button>
</h2>
<div id="collapsedisplayInline" class="accordion-collapse collapse" aria-labelledby="displayInline"
data-bs-parent="#accordion-managed-folder">
<div class="accordion-body">
<p>The image is loaded within the javascript code</p>
<img id="getImageFromManageFolderImg" alt="image" class="container"></img>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="displayAndDownloadInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapsedisplayAndDownloadInline" aria-expanded="false"
aria-controls="collapsedisplayAndDownloadInline">
Display an image and allow this image to be downloaded by clicking on it
</button>
</h2>
<div id="collapsedisplayAndDownloadInline" class="accordion-collapse collapse"
aria-labelledby="displayAndDownloadInline" data-bs-parent="#accordion-managed-folder">
<div class="accordion-body">
<p>The image is loaded within the javascript code</p>
<a id="getImageFromManageFolderA" href="" download="image.png">
<img id="getImageFromManageFolderAImg" alt="image" class="container"></img>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="DownloadPdfInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseDownloadPdfInline" aria-expanded="false"
aria-controls="collapseDownloadPdfInline">
PDF
</button>
</h2>
<div id="collapseDownloadPdfInline" class="accordion-collapse collapse" aria-labelledby="DownloadPdfInline"
data-bs-parent="#accordion-managed-folder">
<div class="accordion-body">
<p>The image is loaded within the javascript code</p>
<a id="getPDFFromManagedFolderA" href="" download="file.pdf">
<span id="getPDFFromManagedFolder" onclick="" class="btn btn-primary">Get PDF file</span>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="DownloadCSSInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseDownloadCSSInline" aria-expanded="false"
aria-controls="collapseDownloadCSSInline">
Local CSS
</button>
</h2>
<div id="collapseDownloadCSSInline" class="accordion-collapse collapse" aria-labelledby="DownloadCSSInline"
data-bs-parent="#accordion-managed-folder">
<div class="accordion-body">
<p>The image <span class="devadvocate-alert">is loaded</span> within the javascript code</p>
</div>
</div>
</div>
</div>
<h2>From resources in project library </h2>
<div class="accordion" id="accordion-project-lib">
<div class="accordion-item">
<h2 class="accordion-header" id="displayInlineProjectLib">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapsedisplayInlineProjectLib"
aria-expanded="false" aria-controls="collapsedisplayInlineProjectLib">
Display an image
</button>
</h2>
<div id="collapsedisplayInlineProjectLib" class="accordion-collapse collapse" aria-labelledby="displayInlineProjectLib"
data-bs-parent="#accordion-project-lib">
<div class="accordion-body">
<p>The image is loaded within the javascript code</p>
<img id="getImageFromProjectLibImg" alt="image" class="container"></img>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="displayAndDownloadInlineProjectLib">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapsedisplayAndDownloadInlineProjectLib" aria-expanded="false"
aria-controls="collapsedisplayAndDownloadInlineProjectLib">
Display an image and allow this image to be downloaded by clicking on it
</button>
</h2>
<div id="collapsedisplayAndDownloadInlineProjectLib" class="accordion-collapse collapse"
aria-labelledby="displayAndDownloadInline" data-bs-parent="#accordion-project-lib">
<div class="accordion-body">
<p>The image is loaded within the javascript code</p>
<a id="getImageFromProjectLibA" href="" download="image.png">
<img id="getImageFromProjectLibAImg" alt="image" class="container"></img>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="DownloadPdfInlineProjectLib">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseDownloadPdfInlineProjectLib" aria-expanded="false"
aria-controls="collapseDownloadPdfInlineProjectLib">
PDF
</button>
</h2>
<div id="collapseDownloadPdfInlineProjectLib" class="accordion-collapse collapse" aria-labelledby="DownloadPdfInline"
data-bs-parent="#accordion-project-lib">
<div class="accordion-body">
<p>The pdf link is updated within the javascript code</p>
<a id="getPDFFromProjectLibA" href="" download="file.pdf">
<span id="getPDFFromProjectLib" onclick="" class="btn btn-primary">Get PDF file</span>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="DownloadCSSInlineProjectLib">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseDownloadCSSInlineProjectLib" aria-expanded="false"
aria-controls="collapseDownloadCSSInlineProjectLib">
Local CSS
</button>
</h2>
<div id="collapseDownloadCSSInlineProjectLib" class="accordion-collapse collapse" aria-labelledby="DownloadCSSInline"
data-bs-parent="#accordion-project-lib">
<div class="accordion-body">
<p>The image <span class="devadvocate-alert2">is loaded</span> within the javascript code</p>
</div>
</div>
</div>
</div>
<h2>Global shared Code (Static Web resources)</h2>
<div class="accordion" id="accordion-global-share-code">
<div class="accordion-item">
<h2 class="accordion-header" id="globalDisplayInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseglobalDisplayInline" aria-expanded="false"
aria-controls="collapseglobalDisplayInline">
Display an image
</button>
</h2>
<div id="collapseglobalDisplayInline" class="accordion-collapse collapse"
aria-labelledby="globalDisplayInline"
data-bs-parent="#accordion-global-share-code">
<div class="accordion-body">
<img alt="image" src="/local/static/image.jpg" class="container"></img>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="globalDisplayAndDownloadInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#globalDollapsedisplayAndDownloadInline" aria-expanded="false"
aria-controls="globalDollapsedisplayAndDownloadInline">
Display an image and allow this image to be downloaded by clicking on it
</button>
</h2>
<div id="globalDollapsedisplayAndDownloadInline" class="accordion-collapse collapse"
aria-labelledby="globalDisplayAndDownloadInline" data-bs-parent="#accordion-global-share-code">
<div class="accordion-body">
<a href="/local/static/image.jpg" download="image.jpg">
<img src="/local/static/image.jpg" alt="image" class="container"></img>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="globalDownloadPdfInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseglobalDownloadPdfInline" aria-expanded="false"
aria-controls="collapseglobalDownloadPdfInline">
PDF
</button>
</h2>
<div id="collapseglobalDownloadPdfInline" class="accordion-collapse collapse"
aria-labelledby="globalDownloadPdfInline" data-bs-parent="#accordion-global-share-code">
<div class="accordion-body">
<a href="/local/static/file.pdf" download="file.pdf">
<span class="btn btn-primary">Get PDF file</span>
</a>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="globalDownloadCSSInline">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseglobalDownloadCSSInline" aria-expanded="false"
aria-controls="collapseglobalDownloadCSSInline">
Local CSS
</button>
</h2>
<div id="collapseglobalDownloadCSSInline" class="accordion-collapse collapse"
aria-labelledby="globalDownloadCSSInline" data-bs-parent="#accordion-global-share-code">
<div class="accordion-body">
<link href="/local/static/my-css.css" rel="stylesheet">
<p>The image <span class="devadvocate-alert">is loaded</span> within the javascript code</p>
</div>
</div>
</div>
</div>
</div>
let getImageFromManageFolderA = document.getElementById('getImageFromManageFolderA')
let getImageFromManageFolderImg = document.getElementById('getImageFromManageFolderImg')
let getImageFromManageFolderAImg = document.getElementById('getImageFromManageFolderAImg')
let getPDFFromManagedFolder = document.getElementById('getPDFFromManagedFolder')
let getPDFFromManagedFolderA = document.getElementById('getPDFFromManagedFolderA')
let getCSSFromManagedFolder = document.getElementById('getCSSFromManagedFolder')
let getImageFromProjectLibImg = document.getElementById('getImageFromProjectLibImg')
let getImageFromProjectLibA = document.getElementById('getImageFromProjectLibA')
let getImageFromProjectLibAImg = document.getElementById('getImageFromProjectLibAImg')
let getPDFFromProjectLibA = document.getElementById('getPDFFromProjectLibA')
let getCSSFromProjectLib = document.getElementById('getCSSFromProjectLib')
// Dynamic setting of the various element
getCSSFromManagedFolder.href = getWebAppBackendUrl('/get_css_from_managed_folder')
getImageFromManageFolderA.href = getWebAppBackendUrl('/get_image_from_managed_folder')
getImageFromManageFolderImg.src = getWebAppBackendUrl('/get_image_from_managed_folder')
getImageFromManageFolderAImg.src = getWebAppBackendUrl('/get_image_from_managed_folder')
getPDFFromManagedFolderA.href = getWebAppBackendUrl('/get_pdf_from_managed_folder')
getImageFromProjectLibImg.src = `/local/projects/${dataiku.defaultProjectKey}/resources/image.jpg`
getImageFromProjectLibA.href = `/local/projects/${dataiku.defaultProjectKey}/resources/image.jpg`
getImageFromProjectLibAImg.src = `/local/projects/${dataiku.defaultProjectKey}/resources/image.jpg`
getPDFFromProjectLibA.href = `/local/projects/${dataiku.defaultProjectKey}/resources/file.pdf`
getCSSFromProjectLib.href = `/local/projects/${dataiku.defaultProjectKey}/resources/my-css.css`
//
getPDFFromManagedFolder.addEventListener('click', () => {
getWebAppBackendUrl('/get_pdf_from_managed_folder')
});
/* Javascript function for external URL */
let externalImageJs = document.getElementById('externalImageJs')
fetch("https://picsum.photos/200/300")
.then(response => response.blob())
.then(image => externalImageJs.src = URL.createObjectURL(image))
import dataiku
import pandas as pd
from flask import request
# Definition of the various resources (This can be done programmatically)
# ## Name of the managed folder
folder = "Resources"
# ## Path name of the files
image = "/image.png"
pdf = "/document.pdf"
css = "/my-css.css"
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieve the file from the managed folder
Args:
folder_name: name of the managed folder
file_name: name of the file
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
return (f.read())
@app.route('/get_image_from_managed_folder')
def get_image_from_managed_folder():
return get_file_from_managed_folder(folder, image)
@app.route('/get_pdf_from_managed_folder')
def get_pdf_from_managed_folder():
return get_file_from_managed_folder(folder, pdf)
@app.route('/get_css_from_managed_folder')
def get_css_from_managed_folder():
return get_file_from_managed_folder(folder, css)
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input
from dash.dependencies import Output
import dataiku
import base64
import logging
logger = logging.getLogger(__name__)
folder_name = "Resources"
image_name = "/image.png"
pdf_name = "/document.pdf"
css_name = "/my-css.css"
# use the style of examples on the Plotly documentation
app.config.external_scripts = ["https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"]
app.config.external_stylesheets = ["https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css",
"/local/static/my-css.css",
f"/local/projects/{dataiku.default_project_key()}/resources/my-css.css"
]
def make_accordion_item(parent_name, name, title, content):
""" Helper to make an accordion object
Args:
parent_name (str): id of the accordion parent
name (str): name of the accordion (must be unique)
title (str): title for the accordion item
content (object): the content of the accordion
Returns:
an html.Div containing the accordion item
"""
return html.Div([
html.H2([html.Button([title],
className="accordion-button", type="button",
**{"data-bs-toggle": "collapse", "data-bs-target": f"#collapse{name}",
"aria-expanded": "false", "aria-controls": f"collapse{name}"}
)], className="accordion-header", id=f"{name}"),
html.Div([html.Div([content], className="accordion-body")],
id=f"collapse{name}", className="accordion-collapse collapse",
**{"aria-labelledby": f"{name}", "data-bs-parent": f"#{parent_name}"}
)], className="accordion-item")
def get_image_from_managed_folder():
""" Read a Png image and return the encoded version
Returns:
a base64 encoded image
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(image_name) as f:
image = f.read()
return 'data:image/png;base64,' + base64.b64encode(image).decode('utf-8')
@app.callback(
Output("downloadManagedFolder", "data"),
Input("btnImageManagedFolder", "n_clicks"),
prevent_initial_call=True,
)
def download_file(_):
"""Serve a file
Args:
_ : not use
Returns:
the file
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(pdf_name) as f:
file = f.read()
return dcc.send_bytes(file, pdf_name[1:])
# build your Dash app
app.layout = html.Div(children=[
html.H2("From external resources", className="display-2"),
html.Div([
make_accordion_item('externalURL', 'displayImage', "Display an image",
html.Div([html.Div(["You can use images coming from an URL by using the classical ",
html.Code('html.Img(src="URL_TO_USE", alt="Alternate text")')]),
html.Img(src="https://picsum.photos/200/300", alt="Image to display")])),
], className="accordion", id="externalURL"),
html.H2("From managed folders", className="display-2"),
html.Div([
make_accordion_item('managedFolder', 'displayImageManagedFolder', "Display an image",
html.Div([html.Div([
"You can use images coming from a managed folder by using the classical, in conjunction with a python funtion ",
html.Code(
'html.Img(src=function_that_returns_the_image, alt="Alternate text")')]),
html.Img(src=get_image_from_managed_folder(), alt="Image to display",
className="container")])),
make_accordion_item('managedFolder', 'downloadFileManagedFolder', "Download a file",
html.Div([html.P([
"For downloading a file, you should use the html.Download, and a button to activate the download"]),
html.Button("Get the file", className="btn btn-primary",
id="btnImageManagedFolder"),
dcc.Download(id="downloadManagedFolder")])),
make_accordion_item('managedFolder', 'cssFromManagedFolder', "Use your own CSS",
html.Div([html.P(["You can not use a CSS file defined in a managed folder"]),
])),
], className="accordion", id="managedFolder"),
html.H2("From resources in project library ", className="display-2"),
html.Div([
make_accordion_item('projectLib', 'displayImageProjectLib', 'Display an image',
html.Div([html.Div(
["You use images coming from resources in the project library by using the classical:",
html.Code("""html.Img(src="URLOfTheResources", alt="Alternate text)""")]),
html.Img(
src=f"/local/projects/{dataiku.default_project_key()}/resources/image.jpg"),
])
),
make_accordion_item('projectLib', 'downloadFileProjectLib', 'Download a file',
html.Div([html.P(
"To be able to use the resources folder in project library, you need to fallback to the usage of the A tag. "),
html.A(children=[
html.Span("Get the PDF", className="btn btn-primary")
], href=f"/local/projects/{dataiku.default_project_key()}/resources/file.pdf",
download="file.pdf")])),
make_accordion_item('projectLib', 'cssFromProjectLib', "Use your own CSS",
html.Div([html.P(
["You just need to adapt the app.config.external_stylesheets to your needs"],
className="devadvocate-alert2"),
])),
], className="accordion", id="projectLib"),
html.H2("Global shared Code", className="display-2"),
html.Div([
make_accordion_item('managedFolder', 'displayImageGlobalSharedCode', "Display an image",
html.Div([html.Div([
"You can use images coming from the Global shared Code by using the classical path ('/local/static/...') ",
html.Code('html.Img(src="URL_TO_USE", alt="Alternate text")')]),
html.Img(src="/local/static/image.jpg", alt="Image to display",
className="container")])),
make_accordion_item('managedFolder', 'downloadFileGlobalSharedCode', "Download a file",
html.Div([html.P(
"To be able to use the global shared code folder, you need to fallback to the usage of the A tag. "),
html.A(children=[
html.Span("Get the PDF", className="btn btn-primary")
], href="/static/local/file.pdf", download="file.pdf")])),
make_accordion_item('managedFolder', 'cssFromGlobalSharedCode', "Use your own CSS",
html.Div([html.P(
["You just need to adapt the app.config.external_stylesheets to your needs"],
className="devadvocate-alert"),
])),
], className="accordion", id="globalSharedCode")
], className="container")
import streamlit as st
import dataiku
import io
import logging
logger = logging.getLogger(__name__)
host = "http://<dssURL>:<port>/"
folder = "Resources"
image = "/image.jpg"
pdf = "/file.pdf"
css = "/my-css.css"
def get_file_from_managed_folder(folder_name, file_name):
"""
Retrieves a file from a managed folder
:param folder_name: name of the folder to retrieve the file from
:param file_name: name of the file to retrieve
Returns:
the file.
"""
folder = dataiku.Folder(folder_name)
with folder.get_download_stream(file_name) as f:
return (f.read())
def get_global_shared_file_url(file):
"""
Retrieves a file from the static web resources
Args:
file: the file to retrieve.
Returns:
the URL to the static web resources file
"""
return host + '/local/static/' + file
st.title('Uses resources')
st.markdown("""## From external URL""")
with st.container():
st.write("### Display an image")
st.image("https://source.unsplash.com/random/1920x1080/?cat=")
st.markdown("""## From managed folder""")
with st.container():
st.write("### Display an image")
st.image(get_file_from_managed_folder(folder, image))
with st.container():
st.write("### Serving a file")
st.download_button("Get the PDF", data=get_file_from_managed_folder(folder, pdf), file_name=pdf)
with st.container():
st.write("### Use your own CSS")
st.write("At the moment, there's no easy way to add an id/class to a streamlit element. However, if you want to use CSS, simply load it like any other file.")
st.markdown("""## From Global shared code""")
with st.container():
st.write("### Display an image")
st.image(get_global_shared_file_url(image))
with st.container():
st.write("### Serving a file")
st.download_button("Get the PDF", data=get_global_shared_file_url(pdf), file_name=pdf)
with st.container():
st.write("### Use your own CSS")
st.write("At the moment, there's no easy way to add an id/class to a streamlit element. However, if you want to use CSS, simply load it like any other file.")
st.markdown("""## From Code studios resources""")
with st.container():
st.write("### Display an image")
with open('../../code_studio-resources/image.jpg', 'rb') as f:
st.image(image=io.BytesIO(f.read()))
with st.container():
st.write("### Serving a file")
with open('../../code_studio-resources/file.pdf', 'rb') as f:
st.download_button("Get the PDF", data=io.BytesIO(f.read()), file_name="file.pdf")
with st.container():
st.write("### Use your own CSS")
st.write("At the moment, there's no easy way to add an id/class to a streamlit element. However, if you want to use CSS, simply load it like any other file.")
st.markdown("## From project resources")
with st.container():
st.write("### Display an image (using URL)")
st.image(f"{host}/local/projects/{dataiku.api_client().get_default_project().project_key}/resources/image.jpg")
st.write("### Display an image (using the Code studio location)")
with open('../../project-lib-resources/static/image.jpg', 'rb') as f:
st.image(image=io.BytesIO(f.read()))
with st.container():
st.write("### Serving a file")
with open('../../project-lib-resources/static/file.pdf', 'rb') as f:
st.download_button("Get the PDF", data=io.BytesIO(f.read()), file_name="file.pdf", key="download_button")
with st.container():
st.write("### Use your own CSS")
st.write("At the moment, there's no easy way to add an id/class to a streamlit element. However, if you want to use CSS, simply load it like any other file.")