Deploy a Django REST API to Heroku in 5 minutes

Sometimes you’re super eager to get started with a new project! Seems easy – you set up a git repo, use django-admin startproject to generate an empty project, start adding dependencies… You want to use Django REST framework for the API, so you install that. Then you need to connect Postgres for the database… Oh, but you want to deploy to Heroku, so you need to configure that DATABASE_URL environment variable and hook that up in settings.py – there was that one project where we had that working already, we can copy/paste it for sure… Celery for async tasks… Redis… 😴… Wait, what were we building again?

If the scenario described above sounds familiar, then like me you’ve run into the problem of boring, repetitive and uncreative work necessary to set up a modern web app project. A lot of boilerplate is needed to get a basic project working and best practices keep changing. Sure, there are solutions like cookiecutter-django which is quite nice, but with ~40 requirements spread across 3 files and ~500 lines of settings spread across 4 files it might be overkill when you’re just getting started. More importantly, while cookiecutter is great for initial project generation, it doesn’t allow you to easily update a project afterwards. Regenerating the project, even when exactly the same prompt answers are selected results in “Error: “my_awesome_project” directory already exists”. As already stated, best practices change over time and it would be useful to have an easy way to update your project boilerplate occasionally.

To address these issues, I’ve developed generator-django-rest – a Yeoman generator for quickly bootstrapping a (relatively simple) Django REST API project that’s deployable to Heroku in 5 minutes. In this post we’ll explain how it works (and why use a JavaScript framework for generating Pythong code 😱), but first let’s see it in action in this screencast:

A bit more than five minutes is enough to get a basic Django REST API online:

Screenshot of a web app showing Django REST framework live in a browser
Great, that’s the boilerplate out of the way. Now we just need to write the actual code!

What we get is more or less a typical project structure (as django-admin would generate it) with some additions to make the project immediately deployable to Heroku (or Dokku if you prefer self-hosting). Django-environ is used to easily configure development and production settings in a 12-factor style using environment variables from a single settings.py file. Pipenv is used for package management – it’s a good way to quickly lock your dependencies to the latest version of common packages (gunicorn, psycopg2 etc.). There are other features too – you can see a full list in the project README.

The most important functionality are three scripts in the scripts/ folder:

  • ./scripts/install.sh – installs and sets everything up to run locally
  • ./scripts/start.sh – starts the development server, database and task runner (Celery)
  • ./scripts/deploy.sh – deploys the app to Heroku

That’s sort of the interface to the generated code – how it works under the hood might change over time, but by remembering these three commands that shouldn’t bother you. This is similar to the way a modern JavaScript project only requires you remember npm install and npm start to start developing. The project also includes a docker-compose.yml file if you prefer to just docker-compose up and work inside Docker containers.

So, why is JavaScript necessary? First of all, there are a lot of great Yeoman generators that can be used for the frontend part of your web app. Yeoman allows one to compose different generators. I plan to cover a combination of generator-django-rest and a frontend code generator in a future post.

There is another reason why I find Yeoman much more useful than Cookiecutter. I typically work on more than one project. When I add something really cool to one of my projects (e.g. a more efficient way to manage settings, like Django-environ), I often want to add it to my other projects too. Upgrading a project at a later point in time can be useful, but even more so – not having this functionality can lead to some serious problems. It’s not very fun when you have 40-something pinned dependencies and a 500-line settings file that you didn’t write a few years into a project when they get outdated. Luckily, with Yeoman we can simply npm install -g generator-django-rest to upgrade the generator and call yo django-rest in an existing project. This will start an interactive prompt showing the differences in the project scaffolding and offering you to select on a per-file basis how you want to handle them. This is similar to how a Debian package prompts you about the config changes after an OS upgrade. I find this to be Yeoman’s killer feature! It will even remember how you answered the original prompts when you first generated the project in a .yo-rc.json file, so you won’t have to repeat yourself.

screenshot of a terminal after yo django-rest was called interactively showing the differences file by file and offering you to choose which files to overwrite
Yeoman allows you to interactively decide how to upgrade your project 🙌

What are my future plans for generator-django-rest? It might be easier said than done, but I plan to keep this productive minimalism mantra. I’ll add new dependencies and improvements only if I think they benefit a wide range of projects and don’t add too much bloat. Better frontend integration is definitely one area I plan to keep improving (most likely by composing generators, which I’ve already experimented with in the past). Also, thanks to the project contributors, we have experimental GraphQL support using Graphene. That’s definitely something I’d like to work more on in the future as an addition to a classical HTTP REST API. I’m also a big fan of pytest, so I’ll probably integrate it in the project eventually as well.

That’s it for now. You can find the instructions on how to try generator-django-rest on GitHub. I’d love to hear your feedback. Happy hacking!

Published by

metakermit

Building apps, analysing data at Punk Rock Dev and sharing weird & cool photographs, drawings, music, films, games... More about me here. You can get new blog posts via RSS or follow @metakermit on Twitter where I also announce new stuff.

Leave a Reply

Your email address will not be published. Required fields are marked *