How I Start Django Projects: My Go-To Setup

Abe | Feb 13, 2025 min read

I’ve been writing Django applications for about 2-3 years now, and I’ve started roughly 5 projects during that time. Every time I kick off a new project, I find myself going through the same setup steps that have worked well for me. I figured I’d share my process - it’s not perfect, but it’s been reliable and keeps me productive.

Cookiecutter Django Is Your Friend

The first thing I do with any new Django project is fire up Cookiecutter Django. After setting up several projects, I’ve got my configuration down to a science. Here’s what my typical setup looks like:

For the basics, I stick with:

  • PostgreSQL 16 (always stay current)
  • UTC timezone (essential for a business app)
  • Email-based user authentication (simpler than username/password)
  • Django Compressor for my frontend pipeline
  • Sendgrid for emails (reliable and easy to set up)

I also always enable:

  • Django REST Framework (because who doesn’t need an API these days?)
  • Celery (for background tasks)
  • Sentry (catches those pesky production errors)
  • Whitenoise (static file serving made simple)

For deployment, I go with:

  • Heroku (quick to deploy, easy to maintain)
  • AWS (for when I need more than what Heroku provides)
  • GitHub Actions for CI

I skip Docker for local development - I prefer working directly with my local environment. I also don’t bother with async Django - haven’t really needed it yet.

One thing I always do is keep my .env files out of version control. Sure, it means a bit more setup time for new team members, but it’s way safer.

Making CSS Less Painful

I use Django LibSass with Django Compressor for my CSS workflow. The main reason I do this is to easily customize Bootstrap - especially theme colors and dark mode. It lets me override Bootstrap’s SCSS variables without needing Node.js or any build tools.

The setup is pretty simple - just install django-compressor and django-libsass, add a few settings, and you’re good to go. Django Compressor handles all the SCSS compilation automatically when the page loads.

I learned this approach from Luke Plant’s blog post and it’s been working great for me. No npm, no webpack, no hassle - just working SCSS in Django.

Dark Mode Because Why Not?

Bootstrap 5.3 comes with dark mode support out of the box, so I always add it to my projects. It’s just a matter of adding data-bs-theme="light" to the base template and including some JavaScript to toggle between modes. I usually throw a theme toggle in the navigation bar using Bootstrap Icons.

I’m actually working on getting this merged into Cookiecutter Django as a default feature - you can check out the discussion in this GitHub issue. Pretty soon you won’t even have to set this up manually!

HTMX Makes Things Nice

I always add HTMX to my projects now. It’s a total game-changer with Django templates - you get modern interactivity without the complexity of a JavaScript framework. Just stick with Django templates and sprinkle in some HTMX attributes.

The setup is minimal - just install django-htmx and add the middleware. I even wrote a small package called django-htmx-messages that lets you use Django’s message framework with HTMX responses. Perfect for toast notifications without page refreshes.

What I love about this setup is that I can build interactive features while keeping everything in Python and Django templates. No context switching to JavaScript required.

Time Zones Are Important

I use TZ Detect for handling time zones in my Django projects. The approach is simple - store everything in UTC, but display times to users in their local timezone. The package handles all the detection and conversion automatically.

This has been a total game-changer for me. I recently built a parking payment system that operates across three different US time zones, and we haven’t had a single timezone-related issue. The package (from adamcharnock/django-tz-detect) just handles everything - it detects the user’s timezone with JavaScript and configures Django accordingly.

When you’re dealing with time-sensitive operations like parking payments across multiple time zones, getting this right from the start saves you from some major headaches down the road.

Logging Setup

For logs, I go with Better Stack (Logtail). I set up JSON logs because they’re easier to work with. Recently, I’ve been using Python’s logger extra parameter to add user context to my logs - it’s pretty neat. You can add things like user IDs or emails to your log entries, and then search through logs for specific users in Better Stack’s interface.

logger.info("User action", extra={"user_id": user.id, "email": user.email})

Final Pieces

Then I wrap up with:

  • Setting up the domain
  • Deploying to Heroku
  • Getting Sentry running
  • Setting up SendGrid for email

That’s my Django setup process. It might look like a lot at first glance, but it’s become second nature after doing it a few times. Each piece serves a purpose and has saved me from headaches down the line.

I’m always tweaking things as I learn new tricks, but this setup has been solid for me. How do you set up your Django projects? I’d love to hear what works for others.