11Starlette encourages a strict separation of configuration from code,
22following [ the twelve-factor pattern] [ twelve-factor ] .
33
4- Configuration should be stored in environment variables, or in a " .env" file
4+ Configuration should be stored in environment variables, or in a ` .env ` file
55that is not committed to source control.
66
77``` python title="main.py"
8- import databases
9-
8+ from sqlalchemy import create_engine
109from starlette.applications import Starlette
1110from starlette.config import Config
1211from starlette.datastructures import CommaSeparatedStrings, Secret
@@ -15,19 +14,20 @@ from starlette.datastructures import CommaSeparatedStrings, Secret
1514config = Config(" .env" )
1615
1716DEBUG = config(' DEBUG' , cast = bool , default = False )
18- DATABASE_URL = config(' DATABASE_URL' , cast = databases.DatabaseURL )
17+ DATABASE_URL = config(' DATABASE_URL' )
1918SECRET_KEY = config(' SECRET_KEY' , cast = Secret)
2019ALLOWED_HOSTS = config(' ALLOWED_HOSTS' , cast = CommaSeparatedStrings)
2120
2221app = Starlette(debug = DEBUG )
22+ engine = create_engine(DATABASE_URL )
2323...
2424```
2525
2626``` shell title=".env"
2727# Don't commit this to source control.
2828# Eg. Include ".env" in your `.gitignore` file.
2929DEBUG=True
30- DATABASE_URL=postgresql://localhost/myproject
30+ DATABASE_URL=postgresql://user:password@ localhost:5432/database
3131SECRET_KEY=43n080musdfjt54t-09sdgr
3232ALLOWED_HOSTS=127.0.0.1, localhost
3333```
@@ -37,7 +37,7 @@ ALLOWED_HOSTS=127.0.0.1, localhost
3737The order in which configuration values are read is:
3838
3939* From an environment variable.
40- * From the " .env" file.
40+ * From the ` .env ` file.
4141* The default value given in ` config ` .
4242
4343If none of those match, then ` config(...) ` will raise an error.
@@ -59,16 +59,11 @@ Secret('**********')
5959' 98n349$%8b8-7yjn0n8y93T$23r'
6060```
6161
62- Similarly, the ` URL ` class will hide any password component
63- in their representations.
62+ !!! tip
6463
65- ``` python
66- >> > from myproject import settings
67- >> > settings.DATABASE_URL
68- DatabaseURL(' postgresql://admin:**********@192.168.0.8/my-application' )
69- >> > str (settings.DATABASE_URL )
70- ' postgresql://admin:Fkjh348htGee4t3@192.168.0.8/my-application'
71- ```
64+ You can use `DatabaseURL` from `databases`
65+ package [here](https://github.com/encode/databases/blob/ab5eb718a78a27afe18775754e9c0fa2ad9cd211/databases/core.py#L420)
66+ to store database URLs and avoid leaking them in the logs.
7267
7368## CommaSeparatedStrings
7469
@@ -101,12 +96,10 @@ is set *after* the point that it has already been read by the configuration.
10196If you're using ` pytest ` , then you can setup any initial environment in
10297` tests/conftest.py ` .
10398
104- ** tests/conftest.py** :
105-
106- ``` python
99+ ``` python title="tests/conftest.py"
107100from starlette.config import environ
108101
109- environ[' TESTING ' ] = ' TRUE'
102+ environ[' DEBUG ' ] = ' TRUE'
110103```
111104
112105## Reading prefixed environment variables
@@ -115,6 +108,7 @@ You can namespace the environment variables by setting `env_prefix` argument.
115108
116109``` python title="myproject/settings.py"
117110import os
111+
118112from starlette.config import Config
119113
120114os.environ[' APP_DEBUG' ] = ' yes'
@@ -139,19 +133,15 @@ First, let's keep our settings, our database table definitions, and our
139133application logic separated:
140134
141135``` python title="myproject/settings.py"
142- import databases
143136from starlette.config import Config
144137from starlette.datastructures import Secret
145138
146139config = Config(" .env" )
147140
148141DEBUG = config(' DEBUG' , cast = bool , default = False )
149- TESTING = config(' TESTING' , cast = bool , default = False )
150142SECRET_KEY = config(' SECRET_KEY' , cast = Secret)
151143
152- DATABASE_URL = config(' DATABASE_URL' , cast = databases.DatabaseURL)
153- if TESTING :
154- DATABASE_URL = DATABASE_URL .replace(database = ' test_' + DATABASE_URL .database)
144+ DATABASE_URL = config(' DATABASE_URL' )
155145```
156146
157147``` python title="myproject/tables.py"
@@ -170,6 +160,7 @@ from starlette.applications import Starlette
170160from starlette.middleware import Middleware
171161from starlette.middleware.sessions import SessionMiddleware
172162from starlette.routing import Route
163+
173164from myproject import settings
174165
175166
@@ -201,7 +192,7 @@ from sqlalchemy import create_engine
201192from sqlalchemy_utils import create_database, database_exists, drop_database
202193
203194# This line would raise an error if we use it after 'settings' has been imported.
204- environ[' TESTING ' ] = ' TRUE'
195+ environ[' DEBUG ' ] = ' TRUE'
205196
206197from myproject import settings
207198from myproject.app import app
@@ -213,7 +204,7 @@ def setup_test_database():
213204 """
214205 Create a clean test database every time the tests are run.
215206 """
216- url = str ( settings.DATABASE_URL )
207+ url = settings.DATABASE_URL
217208 engine = create_engine(url)
218209 assert not database_exists(url), ' Test database already exists. Aborting tests.'
219210 create_database(url) # Create the test database.
0 commit comments