day 1 of my 20 days of django.
i always have a starter template for my django projects, but i couldn't help but feel like it does not cover much: fyi - i still have to do deployment configurations on every project and that's overwhelming.
Sheena O'Connell has an amazing starter template that I think I can pick a few things from it, and most importantly, it shares some of my beliefs ... and it has a big focus on frontend(i always forget about that)
here's the template:
Modern Frontend Django template repo
There are many excellent Django templates out there. They all have different priorities and opinions.
This template repo is different from the rest in that it's primary focus is frontend development, and frontend testing.
You could simply use this repo as a starting point for your own work - download it however you choose, and start adding your own code to the mix.
Or you can poke around and use this as a learning resource. Make sure you understand how everything was wired up and why certain decisions were made.
The latter is the best bet if you want to grow your own skills - it's likely that you will have different preferences, you might want to lay out your project in different ways and use different tools. That's perfectly normal. In fact, creating your own opinionated template repo is a useful learning experience :)
setting the template up
i will use pycharm for this
the documentation looks straightforward.
we will first need to setup the database(make sure that docker is installed):
cd dev_db
docker compose up
next is installing django and other dependencies, and the project is using uv(i have never used it before)
so i need to install it - https://github.com/astral-sh/uv:
on mac:
# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh
or simply:
pip install uv
after that:
Then run uv sync - this will set up a virtual environment in a directory called .venv. This environment works in the usual way.
this is actually very easy ...
Going forward, if you need to run a command using this environment you have the option of activating the environment or using the uv run command. Eg uv run pytest
then of course setting up tailwind:
npm i
npm run tailwind_build
i will disable the social logins for now(too lazy to settup a new app on github). so on config/settings.py:
# SOCIALACCOUNT_PROVIDERS = {
# "github": {
# "VERIFIED_EMAIL": True,
# "SCOPE": [
# "user",
# ],
# "APP": {
# "client_id": env("GITHUB_CLIENT_ID"),
# "secret": env("GITHUB_SECRET"),
# "key": "",
# },
# }
# }
then follow the steps to run the app:
# create the database tables
uv run manage.py migrate
# make some fake data inside the database tables so you have something to look at
uv run manage.py fake_news
# Run the server
uv run manage.py runserver
on a successful setup, your app should be running well on port 8000
running tests
the template is using playwright(end-to-end testing for modern web apps) for tests.
https://playwright.dev/python/
to get started:
uv run playwright install
i think the setup is done... easy, right?
Exploring the Admin
creating an admin user:
uv run manage.py createsuperuser
the template uses unfold - https://unfoldadmin.com/
the unfold configurations in the config/settings.py:
UNFOLD = {
"SITE_TITLE": "News",
"SITE_HEADER": "News",
# "DASHBOARD_CALLBACK": "config.unfold.dashboard_callback",
"SHOW_VIEW_ON_SITE": False,
"SIDEBAR": {
"show_search": True,
"show_all_applications": True,
"navigation": [
{
"items": [
{
"title": _("Home"),
"icon": "home",
"link": reverse_lazy("admin:index"),
},
{
"title": _("Dashboard"),
"icon": "monitoring",
"link": reverse_lazy("admin:dashboard"),
},
]
},
{
"title": _("News"),
"collapsible": True,
"items": [
{
"title": _("Articles"),
"icon": "local_library",
"link": reverse_lazy("admin:news_article_changelist"),
},
],
},
{
"title": _("Accounts"),
"collapsible": True,
"items": [
{
"title": _("Users"),
"icon": "person",
"link": reverse_lazy("admin:accounts_user_changelist"),
},
{
"title": _("Groups"),
"icon": "groups",
"link": reverse_lazy("admin:auth_group_changelist"),
},
],
},
],
},
}
you can learn more about unfold and its configurations here:
https://unfoldadmin.com/docs/
user authentication
the template uses django-allauth
in the template:
- Email/pass registration and authentication
- Email address validation
- Basic email template in place for comms
- Login with Github(disabled it for the moment)
django allauth configurations in config/settings.py:
# AllAuth settings
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = True
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
ACCOUNT_LOGIN_ON_PASSWORD_RESET = True
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_LOGIN_METHODS = {"email"}
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_ADAPTER = "accounts.allauth_account_adapter.AccountAdapter"
ALLOW_SIGN_UPS = True
a custom authentication model is set under the accounts
app. a custom user model with email-based authentication instead of the default username-based one.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
class UserManager(BaseUserManager):
def create_user(
self,
email,
password=None,
is_active=True,
is_staff=False,
is_admin=False,
):
if not email:
raise ValueError("User must have an email address")
if not password:
raise ValueError("User must have a password")
user_obj = self.model(
email=self.normalize_email(email),
)
user_obj.set_password(password)
user_obj.is_staff = is_staff
user_obj.is_superuser = is_admin
user_obj.is_active = is_active
user_obj.save(using=self.db)
return user_obj
def create_superuser(self, email, password=None):
user = self.create_user(
email,
password=password,
is_staff=True,
is_admin=True,
)
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
full_name = models.CharField(null=True, max_length=200)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = "email"
EMAIL_FIELD = "email"
# The fields required when user is created. Email and password are required by default
REQUIRED_FIELDS = []
objects = UserManager()
conclusion
i love this template because it makes it easier to have the following:
- custom user management with django-allauth
- very straightforward allauth configurations and customizations, comes in handy
- a cool django admin using unfold (i prefer using jazzmin or daisy, but unfold is giving me doubts)
- i finally learned how to use django channels for realtime communications ... pretty awesome
fyi: using these learnings to make my template better.
if you wanna try other starter templates, checkout:
https://github.com/lincolnloop/django-layout/tree/main
https://github.com/jefftriplett/django-startproject
https://github.com/wsvincent/lithium
see you soon!