My Cookiecutter Django Setup
Tags: django, sqlite
Published: 2022-07-27 22:10:00

I have some specific requirements for the Django projects I create at my job, so here's how I use [cookiecutter-django](https://github.com/cookiecutter/cookiecutter-django) to help get things going.

## What is Cookiecutter Django?

From the [docs](https://cookiecutter-django.readthedocs.io/en/latest/): "Cookiecutter Django is a project template for jumpstarting production-ready Django projects." 

## My Needs

- SQLite in local development
- Docker for production
- Heroku for site previews
- Custom cloud provider for static files in production

## Setup

Install `cookiecutter` and run it against the [Cookiecutter Django repository](https://github.com/cookiecutter/cookiecutter-django). 

```bash
pip install "cookiecutter>=1.7.0"
cookiecutter https://github.com/cookiecutter/cookiecutter-django
```

Add your own names, emails, etc. Personally, I like using [SendGrid](https://sendgrid.com/) for email because of its great free tier and ease of use. It's also easily scaled to larger workloads for larger client. [Whitenoise](http://whitenoise.evans.io/en/stable/) is the tool I like using for static file serving.

```
project_name [My Awesome Project]: Project Name
project_slug [project_name]: 
description [Behold My Awesome Project!]:
author_name [Daniel Roy Greenfeld]: David Buckley
domain_name [example.com]: example.com
email [david-buckley@example.com]: dev@davidjaybuckley.com
version [0.1.0]: 
Select open_source_license:
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 [1]: 5
timezone [UTC]: 
windows [n]: 
use_pycharm [n]: 
use_docker [n]: y
Select postgresql_version:
1 - 14
2 - 13
3 - 12
4 - 11
5 - 10
Choose from 1, 2, 3, 4, 5 [1]: 1
Select cloud_provider:
1 - AWS
2 - GCP
3 - None
Choose from 1, 2, 3 [1]: 3
Select mail_service:
1 - Mailgun
2 - Amazon SES
3 - Mailjet
4 - Mandrill
5 - Postmark
6 - Sendgrid
7 - SendinBlue
8 - SparkPost
9 - Other SMTP
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 6
use_async [n]: y
use_drf [n]: y
Select frontend_pipeline:
1 - None
2 - Django Compressor
3 - Gulp
Choose from 1, 2, 3 [1]: 2
use_celery [n]: 
use_mailhog [n]: 
use_sentry [n]: 
use_whitenoise [n]: y
use_heroku [n]: y
Select ci_tool:
1 - None
2 - Travis
3 - Gitlab
4 - Github
Choose from 1, 2, 3, 4 [1]: 
keep_local_envs_in_vcs [y]: n
debug [n]: y
```

## Setting Up SQLite

I don't use PostgreSQL in my local environment, so a few things need changed before installing the requirements.

In `requirements/local.txt`, remove `psycopg2` as a dependency (the PostgreSQL package).

```
...
# psycopg2==2.9.3  # https://github.com/psycopg/psycopg2
...
```

Then, in `config/settings/local.py`, replace the line `DATABASES = {"default": env.db("DATABASE_URL")}` with the following.

```python
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ROOT_DIR / "db.sqlite3",
    }
}
```

While in this same local settings file (because I'm not using Docker in the local environment at the moment), replace the line `if env("USE_DOCKER") == "yes":` with:

```python
if env("USE_DOCKER", default="no") == "yes":
```

Finally, there is a migration that has some logic that doesn't work with a SQLite database, so I added this. The file in question is `project_name/contrib/sites/migrations/0003_set_site_domain_and_name.py`.

```
def _update_or_create_site_with_sequence(site_model, connection, domain, name):
    ...
    if (
        created
        and not "ENGINE" in settings.DATABASES["default"]
        or settings.DATABASES["default"]["ENGINE"] != "django.db.backends.sqlite3"
    ): 
        # We provided the ID explicitly when creating the Site entry, therefore the DB
        ...
```

The site that was created in this migration is typically the only site record I have in local so this migration doesn't really affect what I'm doing anyway. I can update the database manually with SQL if needed later. If you have a better way to do this, let me know in the comments, but this worked for me.

## Install Requirements and Migrate Database

Now we're ready to create a virtual environment, install local requirements, migrate the database.

```bash
python -m venv venv
source venv/bin/activate # venv/Scripts/activate for Windows
pip install -r requirements/local.txt
python manage.py migrate
```

Be sure to add `*.sqlite3` to your `.gitignore` file (if it's not already there and you're ready to go in local!