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.
A bit more than five minutes is enough to get a basic Django REST API online:
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
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.
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.
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!