Django from Basics to Production · Django Fundamentals

Users, Login and Permissions

Use Django's auth system: create users with hashed passwords, log in, protect views, and check permissions.

Create a free account to save this page, take notes and track your progress. Sign in

What you'll build

A user with a securely hashed password, a protected view that requires login, a view that requires a specific permission, and requests as anonymous, as a regular user and as a user granted the permission.

The idea

  • django.contrib.auth provides users, groups, permissions and password hashing (PBKDF2 by default; Argon2 and scrypt are supported).
  • authenticate() and login() establish a session; the test client's force_login() does it in tests.
  • @login_required and @permission_required protect function views (LoginRequiredMixin and PermissionRequiredMixin for classes).
  • Permissions like shop.change_order are created per model; assign them through groups.

The code

login_required and permission_required
import django
from django.conf import settings

settings.configure(
    SECRET_KEY="dev-only", ALLOWED_HOSTS=["testserver"], ROOT_URLCONF=__name__, LOGIN_URL="/login/",
    DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
    INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "django.contrib.sessions"],
    MIDDLEWARE=["django.contrib.sessions.middleware.SessionMiddleware",
                "django.contrib.auth.middleware.AuthenticationMiddleware"],
)
django.setup()
from django.core.management import call_command
call_command("migrate", verbosity=0)

from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.models import Permission, User
from django.http import JsonResponse
from django.urls import path

@login_required
def dashboard(request):
    return JsonResponse({"hello": request.user.username})

@permission_required("auth.view_user", raise_exception=True)
def user_list(request):
    return JsonResponse({"users": list(User.objects.values_list("username", flat=True))})

urlpatterns = [path("dashboard/", dashboard), path("users/", user_list)]

ana = User.objects.create_user("ana", "[email protected]", "correct horse battery")
print("stored password:", ana.password.split("$")[0], "... (algorithm, never the password)")
from django.test import Client
c = Client()
r = c.get("/dashboard/")
print("anonymous /dashboard/:", r.status_code, "->", r.headers.get("Location"))
c.force_login(ana)
print("ana /dashboard/:", c.get("/dashboard/").json())
print("ana /users/ without permission:", c.get("/users/").status_code)
ana.user_permissions.add(Permission.objects.get(codename="view_user"))
c.force_login(User.objects.get(pk=ana.pk))          # reload: permissions are cached per user object
print("ana /users/ with permission:", c.get("/users/").json())

Output

stored password: pbkdf2_sha256 ... (algorithm, never the password)
anonymous /dashboard/: 302 -> /login/?next=/dashboard/
ana /dashboard/: {'hello': 'ana'}
ana /users/ without permission: 403
ana /users/ with permission: {'users': ['ana']}

Run this on your computer — see “Get Started” for setup.

Common mistakes

  • Storing passwords yourself instead of set_password()/create_user().
  • Relying on hiding links instead of protecting views.
  • Checking is_staff or usernames in code instead of permissions and groups.

Key points

  • Django hashes passwords and manages sessions for you.
  • Protect views with login_required and permission checks.
  • Grant permissions through groups; check them in views (and object ownership in queries).

Further reading: User authentication in Django · Password management

Practice questions

How does Django store user passwords?

Answer

As a salted hash with the algorithm and iteration count (PBKDF2 by default), never in plain text; set it with set_password() or create_user().

What does @login_required do for anonymous users?

Answer

It redirects them to settings.LOGIN_URL with the original path in the next parameter.

Why are permissions better than checking usernames or is_staff in code?

Answer

They're data you can grant through groups without code changes, and they express exactly which action is allowed.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?