I’ve recently finished writing a fairly large Dash application, see here. The first time I wrote this application, I did not spend much time organizing my codebase, and thus, the code got pretty messy and unorganized. This prompted a full rewrite of the site, where I spent a large effort focusing on how to best organize the different pieces.
The following servers as a guide to highlight the structure of my newer Dash application. The ideas presented in this guide come from my own experience working as in intern in a large React project and common attributes found in open source repositories across the web.
The following is an overview of the structure. I will follow the structure from top down, covering each item and its purpose. Additionally, I’ve created this repository (https://github.com/bradley-erickson/dash-app-structure) to demonstrate the structure and serve as a template for anyone who wants to fork it. Each file in the repository includes more information about the purpose of the file.
dash-app-structure |-- .venv | |-- * |-- requirements.txt |-- .env |-- .gitignore |-- License |-- README.md |-- src | |-- assets | | |-- logos/ | | |-- css/ | | |-- images/ | | |-- scripts/ | | |-- favicon.ico | |-- components | | |-- __init__.py | | |-- footer.py | | |-- navbar.py | | |-- component1.py | |-- pages | | |-- __init__.py | | |-- complex_page | | | |-- __init__.py | | | |-- layout.py | | | |-- page_specific_component.py | | |-- home.py | | |-- not_found_404.py | |-- utils | | |-- __init__.py | | |-- common_functions.py | |-- app.py
The first few items in our structure refer to the virtual environment and package manager. This is a must for handling large applications and ensuring that packages are using the correct versions.
.venv directory is the virtual environment itself where the project specific Python package versions are located. There are various ways to create this, but use the first command below. Note that
.venv is a common name to use for your virtual environment. The
requirements.txt file contains the required Python packages and their respective versions for running the application. I’ve included some additional commands for installing the current requirements, adding new packages, and updating the requirements file.
python -m venv .venv # create the virtual environment .venv\Scripts\pip install -r requirements.txt # install all packages .venv\Scripts\pip install new_package # install a new package .venv\Scripts\pip freeze > requirements.txt # update requirements with new packages
Note: there is a small shift in the Python community away from using
venv and instead using
pipenv. At the time of writing this, I am not as familiar with
pipenv as and I am with using
.env file is where you should house any passwords or keys. This is a common practice as we do not want to directly hardcode keys into your application where a malicious actor could see them. Some common values found in
.env files are
API_KEY. Later on in this guide, we will see how the data is loaded.
.gitignore file is specific to using Git. If you aren’t using Git, you can ignore this; however, you should be using Git or some other Version Control System. The
.gitignore specifies files that should not be included when you commit or push your code.
I use the basic Python
.gitignore file, located at https://github.com/github/gitignore/blob/main/Python.gitignore. Notice that both the
.venv directory and
.env file are included here.
LICENSE file determines how your code should be shared. If you are keeping your code completely private, you do not need a license; however, you should still include one.
For more inforamtion on choosing the correct license, see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository.
README.md file should specify how to install and run your application. This includes, but is not limited to, installing packages, mentioning which environemnt variables need to be set, and running the application.
src directory is where to house all of the code. We will dive into each item below.
Note: some of the mentioned directories are not incldued in the sample repository as Git ignores empty directories by default.
The components directory should contain common components used throughout the application. The simplest example are that of the navigation bar,
navbar.py, and footer element,
footer.py. All-in-one components should also be stored here. Defining each of these components in their own file is good practice. Additionally, I import each component into the
__init__.py file. This allows for easier imports like the following:
from components import navbar, footer
Large structured applications rely on the new Dash Pages feature, currently only available via Dash Labs. This guide will be updated once Dash Pages is included in an official Dash release. For more information, see the community post at https://community.plotly.com/t/introducing-dash-pages-a-dash-2-x-feature-preview/57775.
The static pages should be included immediately under the pages directory. While the complex pages should be included in their own directory inside the pages.
See the files within the
complex_page directory and the pages forum post for more information about how to structure more complex pages.
The utilities directory,
utils, is meant for common functions run throughout the application. Splitting these up into specific files allows for more organized code.
In the example repository, there are 2 files,
api.py file reads in our environment variables to get the
API_KEY. The sample API called does not require a key; however, I deemed it important to include anyways. This file also defines a function that formats the inputs to call the API. To call the API, we just need to import and call the
images.py file focuses on anything to do with images shown in our application. Some of the main functionality includes reading in local images and converting them to encoded strings so they show up properly. Addtionally, if you are displaying images hosted on some Content Distribution Network (CDN), you might also define a method for formatting the url here.
app.py file is the entrypoint to defining and running the application. This is where we define the Dash app, set external stylesheets, and run the app.
As it stands, Dash requires the
app object for defining
long_callbacks. Since this is the only place in the codebase that can access the app object, without ciruclar imports, this file should house any
I hope this guide helps you to build the best Dash app you can!