dj-database-url for Django database configuration
Use Database URLs in your Django Application.
At a glance
- What is it?
- dj-database-url turns a DATABASE_URL into Django's DATABASES configuration, with direct URL parsing and custom backend registration. It suits applications that want environment-based database configuration, but malformed URLs and backend-specific settings still require attention.
- Who is it for?
- Adopt dj-database-url if the application benefits from one environment variable across Django deployments and the required database backend is supported or can be registered. Do not adopt it as a complete database configuration layer if credentials need extensive URL encoding or custom backends require substantial post-processing.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why dj-database-url fits environment-based Django deployments
dj-database-url addresses a narrow but common Django configuration problem: keeping the database connection details in a URL supplied by the deployment environment. Its `config()` function reads `DATABASE_URL` and returns a dictionary that can be assigned to `DATABASES['default']`. This is useful for teams that switch among local, hosted and production environments without rewriting Django settings for each one.
The utility is intended for Django developers rather than database clients or migration tools. It does not connect to a database or execute queries. Its responsibility ends at producing the connection dictionary expected by Django. The README also gives the project a 12factor-inspired framing, which places database access alongside other services configured through environment variables.
There are two entry points. `config()` reads an environment variable, while `parse()` accepts a URL directly. That distinction matters when an application uses more than one database or when a URL already comes from another configuration source. The package depends on `django>=4.2`, and `pyproject.toml` classifies support for Django 4.2, Django 5.2 and Django 6, with Python 3.10 through Python 3.14 listed in its classifiers.
How config() and parse() build Django DATABASES entries
The central data flow is short: a database URL enters `config()` or `parse()`, dj-database-url parses it, and the returned dictionary becomes a Django database configuration. `config()` defaults to the `DATABASE_URL` environment variable. Its `env` argument selects another variable, which allows separate URLs for databases such as a primary application database and an analytics database.
The URL's scheme selects support for PostgreSQL, PostGIS, MySQL, MySQL (GIS), Oracle, Oracle (GIS), Redshift, CockroachDB, Timescale, Timescale (GIS) and SQLite. Based on the documented configuration examples, the resulting dictionary contains Django connection parameters such as `ENGINE` and `NAME`; the README's custom-backend example also demonstrates that a parsed configuration can include backend-specific parameters.
Django connection behavior is controlled through two documented arguments. `conn_max_age` sets Django's `CONN_MAX_AGE`, allowing connections to persist between requests for the supplied lifetime in seconds. When omitted, it follows Django's default of `0`. `conn_health_checks` sets `CONN_HEALTH_CHECKS`, which was introduced in Django 4.1 and checks a persisted connection at the beginning of each request. When omitted, it follows Django's default of `False`. The README recommends enabling connection health checks when `conn_max_age` is non-zero, although the connection reuse decision still belongs to the application operator.
Installing dj-database-url and configuring the first database
The README identifies PyPI as the installation source and gives `pip` as the installation command. In a Django project's environment, install the package before importing it in `settings.py`.
pip install dj-database-urlFor an application that does not already define `DATABASES`, configure the default database from `DATABASE_URL` during Django settings loading. dj-database-url will return the dictionary that Django expects for the default connection.
import dj_database_url
DATABASES = {
'default': dj_database_url.config(
conn_max_age=600,
conn_health_checks=True,
),
}At startup, `DATABASE_URL` must contain a valid database URL. The README requires special characters to be URL-encoded. For example, a password containing `#` cannot appear literally because it changes how the URL is parsed.
postgres://user:p%23ssword!@localhost/foobarIf `DATABASE_URL` is not defined, `config()` without a `default` does not receive a URL to parse. A deployment can either supply the variable or add a fallback URL to the call. The fallback is configuration data, so a real value should come from the project or deployment environment rather than being copied blindly from documentation.
Multiple databases, empty variables and direct URL parsing
Use the `env` argument when one Django application needs more than one configured database. Each call can read a different environment variable and apply its own fallback.
import dj_database_url
DATABASES = {
'default': dj_database_url.config(),
'analytics': dj_database_url.config(
env='ANALYTICS_DATABASE_URL',
default='sqlite:///analytics.sqlite3',
),
}In this example, the default database uses `DATABASE_URL`, while the analytics database uses `ANALYTICS_DATABASE_URL`. If `ANALYTICS_DATABASE_URL` is absent, the configured SQLite fallback is used. This is a more precise fallback mechanism than a global default because it applies to the environment variable selected by that specific call.
An empty selected variable has separate behavior. The README states that if the selected variable is set to an empty string, `config()` returns an empty dictionary rather than applying `default`. Deployments should therefore distinguish an unset variable from a variable deliberately set to `''`.
For code that already holds a URL, `parse()` avoids environment-variable access. It returns the same kind of Django connection dictionary.
DATABASES['default'] = dj_database_url.parse(
'postgres://...',
conn_max_age=600,
conn_health_checks=True,
)The README does not document URL precedence, query-parameter handling or a complete schema reference in the available text. Those details should not be assumed when URLs include vendor-specific options.
Custom backend registration and its configuration limits
The built-in support list does not cover every database driver an organization may use. `register()` maps a custom URL scheme to a Django database engine path, allowing a URL such as `mysql-connector://` to produce an `ENGINE` value that Django can use. Registration should occur only once.
import dj_database_url
dj_database_url.register("mysql-connector", "mysql.connector.django")Some engines require adjustments after parsing. The README states that Oracle and MSSQL, for example, may expect `PORT` to be a string. It also demonstrates post-processing functions for Redshift and Snowflake. When a function is supplied, `register()` is used as a decorator.
import dj_database_url
@dj_database_url.register("mssql", "sql_server.pyodbc")
def stringify_port(config):
config["PORT"] = str(config["PORT"])This design makes dj-database-url extensible, but it also defines its boundary. The package can construct a Django dictionary and apply explicitly registered transformations. It does not eliminate driver-specific configuration. A backend may still require an installed driver, exact option names, account or warehouse settings, and application-specific schema handling. The Snowflake example, for instance, moves parsed URL components into `ACCOUNT`, `SCHEMA`, `WAREHOUSE` and `ROLE`, showing that custom support can contain nontrivial application policy.
The README also documents `test_options` for Django's test configuration.
DATABASES['default'] = dj_database_url.config(
default='postgres://...',
test_options={'NAME': 'mytestdatabase'},
)That attribute adjusts the generated dictionary for Django test database creation; it is not a separate test runner.
dj-database-url maintenance, compatibility and adoption constraints
The repository is not archived. Its last push was on 2026-10-13, and the listed releases include v3.1.2 on 2026-02-19, v3.1.1 on 2026-02-16 and v3.1.0 on 2026-01-04. Those facts indicate recent repository activity and recent published releases, but they do not remove the need to match the installed version with the Django version used by the application.
The package metadata requires Python 3.10 or later and Django 4.2 or later. Its supported-database claim is tied to recognizable Django engines, not every database product. A team using a different driver must verify that `register()` is sufficient or prepare a post-processing function.
dj-database-url uses the BSD-3-Clause license. That identifier is confirmed by both the repository description and `pyproject.toml`, which also lists the license file as `LICENSE`. The exact obligations and applicability should be checked in that file for the intended distribution; this review does not provide legal advice.
The clearest wrong-tool case is an application whose database configuration cannot be represented safely by a valid URL or needs extensive per-backend logic unrelated to parsing. A literal unencoded password is another boundary because the parser raises `ValueError` instead of reconstructing arbitrary connection details. In such cases, direct Django configuration may be clearer. For conventional Django deployments that already expose a database URL, dj-database-url removes repeated dictionary construction without becoming a database management layer.
Editorial conclusion
Adopt dj-database-url if the application benefits from one environment variable across Django deployments and the required database backend is supported or can be registered. Do not adopt it as a complete database configuration layer if credentials need extensive URL encoding or custom backends require substantial post-processing. First verify that every deployment supplies a valid URL and that each backend's ENGINE, PORT, OPTIONS and test settings match the driver's requirements.
Frequently asked questions
How do I install and configure dj-database-url in Django?
Install it with `pip install dj-database-url`, import it in Django settings, and assign `dj_database_url.config()` to the default entry in `DATABASES`. By default, `config()` reads `DATABASE_URL`.
How does dj-database-url handle multiple databases?
Pass a different environment variable through `env` for each `config()` call. The README shows `ANALYTICS_DATABASE_URL` with a SQLite default for a second database.
What happens when the selected database URL environment variable is empty?
The README states that `config()` returns an empty dictionary when the selected variable is set to an empty string. It does not apply the `default` URL in that case.
Can dj-database-url support a non-default Django database backend?
Yes, a backend can be registered with a URL scheme and Django engine path. Some backends also need a post-processing function registered as a decorator to adjust fields such as `PORT`.
Why does dj-database-url raise ValueError for some database URLs?
Input strings must be valid URLs, so special characters in credentials must be URL-encoded. For example, a password containing `#` must use `%23` rather than a literal `#`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jazzband-dj-database-url)Was this useful?