Django includes a complete authentication system — user models, login/logout views, password hashing, and permission management.

Built-In User Model

  from django.contrib.auth.models import User

user = User.objects.create_user(
    username="alice",
    email="[email protected]",
    password="secure_password123",
)

user.is_authenticated  # True (when logged in)
user.is_staff          # admin access
user.is_superuser      # all permissions
  

Login and Logout Views

Django provides ready-made auth views:

  # urls.py
from django.contrib.auth import views as auth_views

urlpatterns = [
    path("login/", auth_views.LoginView.as_view(template_name="login.html"), name="login"),
    path("logout/", auth_views.LogoutView.as_view(), name="logout"),
    path("register/", views.register, name="register"),
]
  
  # views.py
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect

def register(request):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect("home")
    else:
        form = UserCreationForm()
    return render(request, "register.html", {"form": form})
  

Protecting Views

  from django.contrib.auth.decorators import login_required, permission_required

@login_required
def dashboard(request):
    return render(request, "dashboard.html")

@permission_required("blog.can_publish", raise_exception=True)
def publish_post(request, pk):
    ...
  

Class-based views:

  from django.contrib.auth.mixins import LoginRequiredMixin

class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    fields = ["title", "content"]
    login_url = "/login/"
  

Templates — Show Auth State

  {% if user.is_authenticated %}
  <p>Welcome, {{ user.username }}!</p>
  <a href="{% url 'logout' %}">Logout</a>
{% else %}
  <a href="{% url 'login' %}">Login</a>
{% endif %}
  

Custom User Model

For production, define a custom user model early:

  # models.py
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    bio = models.TextField(blank=True)
    avatar = models.ImageField(upload_to="avatars/", blank=True)
  
  # settings.py
AUTH_USER_MODEL = "accounts.CustomUser"
  

Define this before your first migration. Changing later is painful.

Password Security

Django hashes passwords automatically:

  from django.contrib.auth.hashers import make_password, check_password

hashed = make_password("my_password")
check_password("my_password", hashed)  # True
  

Built-in validators enforce minimum length and common-password checks:

  AUTH_PASSWORD_VALIDATORS = [
    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
]
  

Groups and Permissions

  from django.contrib.auth.models import Group, Permission

editors = Group.objects.create(name="Editors")
publish_perm = Permission.objects.get(codename="can_publish")
editors.permissions.add(publish_perm)

user.groups.add(editors)
user.has_perm("blog.can_publish")  # True
  

Django’s auth system handles the security fundamentals so you can focus on application logic.