Warning: Bocadillo is now UNMAINTAINED. Users are recommended to migrate to a supported alternative, such as Starlette or FastAPI. Please see #344 for more information.
Configuration
Configuration is a required step before the application can be served by an ASGI server such as uvicorn.
Except for Retrieving settings, you can safely ignore this section if you generated your project using the Bocadillo CLI, which should have set up a settings module and a server entry point for you.
Configuring applications
Configuration occurs when the configure()
helper is called with the app
that should be served. This has the effect of calling all registered plugins, which in turn set up features such as CORS, HTTPS redirection, etc.
NOTE
Since it prepares the app
for serving, configure()
can only be called once.
Besides the mandatory app
argument, configure()
can be given one or both of the following:
- A settings object or module, e.g.
configure(app, settings)
. In this case, individual settings are obtained from upper-cased constants, e.g.ALLOWED_HOSTS = ["example.com"]
.
You can prevent Bocadillo from treating intermediary variables as settings by prefixing them with a leading underscore, e.g. _some_var
or _SOME_VAR
.
- Arbitrary settings passed as keyword arguments, e.g.
configure(app, ALLOWED_HOSTS=["example.com"])
.
Retrieving settings
If you ever need to access settings at runtime, you can use the settings
object.
This object can be imported from the bocadillo
package, and gets populated once configure()
is called (which has a few gotchas — see warning below). Besides regular dot notation, you can use the dict-like .get()
method to retrieve a setting with an optional default value.
Accessing an attribute of settings
before configure()
was called will raise an error.
For this reason, you should only access settings inside a function or a method. In other words, you should not access settings at the top level of a Python module.
Here is an example:
# myproject/app.py
from bocadillo import App, settings
app = App()
@app.route("/")
async def index(req, res):
if settings.get("PUBLIC", False):
res.text = "Hello, world!"
else:
res.text = "Coming soon!"
Accessing settings is typically needed when implementing plugins.
Settings module
The recommended way to define configuration is through a settings module, i.e. a .py
file which declares settings as upper-cased constants.
We recommend you use Starlette's Config helper to define settings. It reads configuration from environment variables and also supports .env
files located at the project root directory. This way, you only need one settings module for all environments (production, local development, etc.).
Here's an example:
# myproject/settings.py
from starlette.config import Config
config = Config(".env")
ALLOWED_HOSTS = ["localhost", "example.com"]
HSTS = config("HSTS", default=False)
And the corresponding app.py
# myproject/app.py
from bocadillo import App, configure
from . import settings
app = App()
configure(app, settings)
The from . import settings
statement above is a relative import. It only works if the code is located inside a package — here, myproject
. If you don't use a package, you will need to use absolute imports, e.g. import settings
.
For more information on Python imports, see Absolute vs Relative Imports In Python (Real Python).
Server entry point
Although the minimal working app instanciates and configures the app
within the same script, it is recommended to perform these operations separately. This allows you to change settings at runtime, and encourages more decoupling between settings and applications.
To achieve this, you should create a server entry point, i.e. a Python script typically named asgi.py
where configure()
is called to prepare the app
before it is served by the ASGI server.
For example, remove the call configure()
in app.py
:
# myproject/app.py
from bocadillo import App
app = App()
# ...
and move it to a new asgi.py
script:
# myproject/asgi.py
from bocadillo import configure
from .app import app
from . import settings
configure(app, settings)
You must now serve the app using $ uvicorn myproject.asgi:app
instead of $ uvicorn myproject.app:app
.
← Applications Routing →