A recent list claiming 12 libraries to turn a Python script into production software made me pause. As the maintainer of a self-hosted AWS drift detector, I reviewed each suggestion against my stack. The result? Eleven libraries crossed off the list—not because I’m minimalist, but because Django handled them before I wrote a single line of code.
The real insight isn’t in the count. It’s in recognizing that picking a framework is itself the most significant dependency decision you’ll make. Here’s how one choice reshaped my production stack—and where the framework still left room for improvement.
Ten libraries replaced by a single framework choice
Choosing Django isn’t about avoiding dependencies. It’s about inheriting solutions to problems you didn’t realize you’d solved. Here’s what disappeared when I adopted Django, and why adding a second library would have created more problems than it solved:
- `click` → Django management commands
My CLI isn’t a separate framework; it’s Django’s built-in manage.py commands. Argument parsing, help text, type coercion, and command discovery all come for free. Introducing click would create a parallel CLI layer that needs its own documentation, testing, and maintenance.
- `SQLAlchemy` → Django ORM + `psycopg2`
I work with PostgreSQL via dj-database-url, which lets me switch databases with a URL change. Adding SQLAlchemy would mean maintaining two ORMs, two migration systems, and two identity maps—inviting subtle bugs and doubling cognitive load.
- `marshmallow` → Django forms + boundary normalization
Untrusted input enters through Django’s form and model validation layer. AWS scan results get normalized into a fixed structure at the edge. The validation exists; it’s just not a separate library.
- `schedule`/`celery` → `django-apscheduler`
My periodic scans run via Django’s scheduler. Celery would require Redis and a distributed task queue—complexity I haven’t earned and would need to debug at 2 AM. I’ve already written about the risks of duplicate schedulers in Django apps.
- `structlog` → Standard library logging
The original problem structlog solves is graduating from print statements in scripts. My codebase uses logging with getLogger(__name__)—a solved problem before structlog entered the picture.
- `python-dotenv` → Docker Compose environment injection
In production, docker compose injects environment variables. I read them via os.getenv at the settings boundary. python-dotenv is useful for local development when not using containers, but it’s not a production dependency.
- `tqdm` → Structured log lines
My scan jobs run on schedules or web requests, not in attended terminals. A progress bar has no audience; a timestamped log line does.
- `Docker SDK` → Containerized deployment
SyncVey is a container (docker compose up). The SDK isn’t needed to drive Docker from Python; the container is the deployment unit.
- `pytest` → Django’s test runner
Django’s built-in test framework handles unit, integration, and database tests out of the box. Adding pytest would require extra configuration and risk breaking Django’s assumptions.
- `boto3` → Already handled by AWS SDK
Boto3’s built-in retry logic already retries AWS API calls. Adding it separately would duplicate that functionality.
These ten libraries didn’t vanish because I’m dogmatic. They vanished because Django answered their core use cases before I needed to import them.
The two real gaps the framework left behind
No framework is perfect. Even after inheriting ten solutions, two gaps remained. Auditing the list revealed them—and forced me to confront a stray print statement that had slipped through my logging conventions.
- `tenacity` for non-AWS HTTP retries
Boto3 handles retries for AWS calls, but my two non-framework HTTP calls—a Slack webhook post and an EOL calendar fetch—use raw urllib with no retry logic. A transient network error on either call fails the operation. This is exactly the use case the list highlights, and Django doesn’t cover it because it’s not a web framework concern. I should add tenacity here.
- `structlog` for structured logging
I’m using Python’s standard library logging, which works. But structured JSON logs would make scan jobs and attribution failures queryable instead of greppable. The list didn’t just suggest a library; it made me look at my logging practices. In the process, I found a print that had bypassed my own conventions.
The lesson isn’t that frameworks eliminate all dependencies. It’s that they redefine where your dependencies belong.
The framework paradox: when to choose, and when to avoid
Frameworks excel when your project’s shape matches their default assumptions. A self-hosted service with periodic tasks, a database, and a web interface? Django’s model-view-template architecture fits like a glove. A data-munging script with no persistence and no surface area? That’s a weekend project where click, tqdm, and python-dotenv are the right tools.
The mistake isn’t choosing a framework. It’s assuming the same list of libraries works for both scenarios. Pretending one set of defaults fits every problem is how you end up with two ORMs, two CLI tools, and two logging layers—each needing synchronization, testing, and maintenance.
Audit your stack like a senior engineer
Before you pip install your next dependency, ask three questions:
- Does my framework already solve this?
- CLI tools → Check built-in management commands.
- ORM needs → Check your framework’s database layer.
- Configuration → Check environment variable handling.
- Logging → Check your framework’s logging conventions.
- If I add this library, will I be maintaining two copies of the same thing?
Two ORMs. Two CLI frameworks. Two configuration layers. Each pair introduces synchronization overhead and subtle bugs.
- Where does my framework leave gaps?
For me, it was retries on non-framework HTTP calls and structured logging. For you, it might be async tasks, real-time features, or specialized data processing.
The leverage in production stacks isn’t in the number of libraries. It’s in the one choice that pre-answers ten questions—and the discipline to audit the two it leaves behind.
AI summary
Python projelerinizi üretime hazır hale getiren en iyi 12 kütüphane ve hangilerinin gerçekten ihtiyaç duyulduğunu anlamak için Django kullanıcılarının deneyimlerini keşfedin.