django / django/new-features

Integrate Environment Variable Management (Inspired by django-environ) into Django Core

Open
#61 5 comments 42 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
188
Forks
7
PR merge metrics
No merged PRs in 30d

Description

### Code of Conduct

- [x] I agree to follow Django's Code of Conduct

### Package Information

django-environ

### Problem

Django projects, by default, store sensitive configurations like `SECRET_KEY`, `DEBUG` status, database credentials, and API keys directly within `settings.py` files using literal strings or booleans. This practice presents several critical issues:

1. **Security Vulnerability**: Storing sensitive information directly in `settings.py` means these configurations are often committed directly into version control systems (e.g., Git repositories). If a repository is ever accidentally exposed or breached, critical configurations become publicly accessible, leading to severe security risks.

2. **Violation of The Twelve-Factor App Principles (Config)**: The third principle of The Twelve-Factor App methodology explicitly states, "Store config in the environment." Django's current default project setup directly contradicts this fundamental principle, making it harder for developers to build robust, scalable, and secure applications that adhere to modern best practices.

3. **Lack of Environment Agnosticism**: Different deployment environments (development, staging, production) require different configurations (e.g., `DEBUG=True` for development, `DEBUG=False` for production; different database connections). Hardcoding these in `settings.py` necessitates manual changes or complex, often brittle, conditional logic within the settings file itself, which is error-prone and difficult to manage across various environments.

4. **Poor Developer Experience**: Developers often need to manually create `.env` files and parse them, or rely on `os.environ` which lacks type conversion capabilities. This adds unnecessary boilerplate and mental overhead, especially for new projects or developers unfamiliar with managing environment variables effectively.

### Rationale

While `django-environ` is an excellent third-party package that addresses these problems, its core functionality, robust environment variable management with type conversion, is fundamental to building secure, maintainable, and Twelve-Factor compliant web applications. This functionality should not be an optional add-on but a foundational component of Django itself for the following reasons:

1. **Security by Default**: Integrating environment variable management directly into Django's initial project setup would make secure configuration the default, rather than an afterthought. This helps prevent common security pitfalls, especially for new developers who might not be aware of the "Config" principle or the existence of `django-environ`. Django's responsibility is to guide users towards secure development practices.

2. **Adherence to Industry Standards**: The Twelve-Factor App methodology is a widely accepted standard for building robust web applications. By incorporating environment variable configuration into its core, Django would explicitly align itself with this critical principle, enhancing its reputation as a modern, best-practice-oriented framework.

3. **Improved Developer Experience and Reduced Boilerplate**: Currently, developers must install `django-environ`, import it, and then adapt their `settings.py` files. By making this a built-in feature, Django can provide a seamless experience:

- **Automatic Type Conversion**: The current `os.environ` only returns strings. A core feature would handle automatic type conversion for common data types (e.g., `"True"` to `True`, `"123"` to `123`, `"item1,item2"` to `['item1', 'item2']`), significantly simplifying `settings.py` and reducing parsing errors.

- **Consistent API**: A standardized, Django-native API for accessing environment variables ensures consistency across all Django projects, making it easier for developers to jump between different projects without learning varying configuration patterns.

- **Automatic `.env` File Loading**: Django could automatically look for and load a `.env` file in the project root, just as `django-environ` does, streamlining local development setup.

4. **Guidance and Best Practices**: Including this functionality in Django's core allows the framework to provide clearer guidance on managing configurations. This includes the ability to automatically generate a `.env.example` file with the initial project, mirroring best practices seen in other popular frameworks like Laravel, which effectively uses `.env` files and `.env.example` for configuration. This helps developers understand exactly what environment variables are expected.

5. **Elimination of External Dependency**: For a feature so crucial to security and deployment, relying on an external package introduces an additional dependency that might become a point of failure or maintenance burden. Integrating it into core ensures long-term stability and support.

### Additional Details

- The goal is not to re-implement `django-environ` verbatim, but to integrate its core principles and functionalities (robust environment variable parsing with type conversion, `.env` file loading) into Django's foundational configuration system.

- The implementation should be flexible enough to allow developers to still use `os.environ` directly if they choose, but the recommended and default approach for Django configurations should leverage the new built-in functionality.

- Considerations for prefixing environment variables (e.g., `DJANGO_SECRET_KEY`) to avoid conflicts with other system environment variables could be part of the design.

- The `.env.example` file generation should be part of `django-admin startproject`, providing an immediate template for required environment variables.

### Implementation Details

- A new module or utility function within Django (e.g., `django.conf.env`) could be introduced to handle the parsing and type conversion of environment variables. Or for simplicity, install `django-environ` as default package, and use it to handle `.env`.

- This utility would prioritize `os.environ` and then fall back to loading from a `.env` file if it exists in the project root (or a configurable path).

- The API should be designed to be intuitive and similar to how `django-environ` currently operates, offering methods like `env('VAR_NAME', default='fallback', cast=bool)`.

- The `startproject` template should be updated to utilize this new `env` utility for common settings like `SECRET_KEY`, `DEBUG`, database settings, etc., and to generate a basic `.env.example` file.

- Consider a small, dedicated configuration object or class to hold parsed environment variables, potentially allowing for more complex nested structures if needed, similar to how `django-environ` handles `DATABASE_URL` or `CACHE_URL`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.