How I Start: Django, Tailwind, HTMX (part 2)
In part 1, I set up the project, a sensible
.gitignore, tailwind, and live reloading along with some run targets for PyCharm. Now it’s time to finish up the housekeeping.
Housekeeping: Move Configuration into the Environment
This doesn’t strictly need to be done at this early stage, but I find that doing so is a protective habit, especially for projects that sit on postgres. Thanks to the
.gitignore from part 1, if secrets go into
.env files, they can never land in source control by mistake.
Before starting, make sure we can use
.env files with
poetry add python-dotenv
First add the relevant values to the
echo DEBUG=True >>.env echo DJANGO_SECRET_KEY=$(poetry run python -c "import secrets; print(secrets.token_urlsafe())") >>.env
import environ at the top of
config/settings.py and change
DJANGO_SECRET_KEY to pull from there instead:
import environ from dotenv import load_dotenv load_dotenv() env = environ.FileAwareEnv( # set casting, default value DEBUG=(bool, False) ) ... # False if not in os.environ because of casting above DEBUG = env('DEBUG') # SECURITY WARNING: keep the secret key used in production secret! # Raises Django's ImproperlyConfigured # exception if DJANGO_SECRET_KEY not in os.environ SECRET_KEY = env('DJANGO_SECRET_KEY')
If I were using postgres for this project, the URL for that would also come from
.env. See the django-environ documentation for details.
Housekeeping: Custom User Model
Having once wasted quite a bit of time adding a custom user model after the fact, I now do this before I run
migrate for the first time.
Until/unless I’m ready to move my project to allauth, I like the starting point provided by django-authuser. I copy it into my tree since the likelihood that I want to modify it is high and the likelihood that I want to track upstream changes is low.
curl -L -o django-authuser.zip https://github.com/sesh/django-authuser/archive/refs/heads/main.zip unzip django-authuser.zip mv django-authuser-main authuser rm django-authuser.zip
Then I add it to INSTALLED_APPS and set my user model in
INSTALLED_APPS = [ ..., "authuser", ..., ] AUTH_USER_MODEL = "authuser.User"
config/urls.py to route traffic to its views:
urlpatterns = [ path("admin/", admin.site.urls), path("accounts/", include("authuser.urls")), path("__reload__/", include("django_browser_reload.urls")), path("", include("reading_journal.urls")), ]
With that done, I run migrate for the first time and create a superuser to make sure everything is working:
poetry run python manage.py makemigrations poetry run python manage.py migrate poetry run python manage.py createsuperuser
If everything is working, I should be prompted for my superuser’s email and password but not a username.
That was a short Part 2, but this is a good stopping point. Part 3 will build out models and views.
I’m trying on Kev Quirk’s “100 Days To Offload” idea. You can see details and join yourself by visiting 100daystooffload.com.
This is day 3.