Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Django’s built-in authorization links users and groups to permissions, while content types identify the models those permissions apply to. The key distinction is that Django’s default ModelBackend checks model-level permissions—not whether a particular user may access a particular database row.

Which Django auth models are involved?

The built-in authorization system centers on four models: User, Group, Permission, and ContentType. A permission points to a content type, which identifies the model it concerns. Users can receive permissions directly or through groups.

Django’s authentication and contenttypes applications supply the models and migrations needed for this system. The exact physical database table and many-to-many join-table names depend on the Django version, migrations, database, and user-model configuration in a project. Treat the model relationships as the stable mental model; inspect the project’s migrations and database before relying on specific SQL table names.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Permission fields and checks

A permission has a human-readable name, a machine-oriented codename, and a reference to its content_type. The codename is used in checks in the form <app label>.<permission codename>. For example, user.has_perm("blog.change_post") asks whether the user has the change_post permission associated with the blog app.

With django.contrib.auth installed, Django creates the standard add, change, delete, and view permissions for each model in installed applications. Applications can define custom permissions in model metadata or create and assign them explicitly.

How do users, groups, and permissions connect?

Permissions can be assigned directly to an individual user or attached to a group. Users can belong to multiple groups, and they receive the permissions granted to each group they belong to. This makes groups useful as reusable role bundles, while direct assignments are better suited to individual exceptions.

Grant method Best fit How a change propagates Maintenance trade-off
Direct user permission An individual exception or user-specific grant Affects that user Simple for one-off cases, but many per-user assignments are harder to manage centrally
Group permission A reusable set of permissions for a role or team Applies to the group’s members Central group changes are easier to maintain, but group membership must reflect the intended access

Effective permissions may also come from configured authentication backends. Django combines grants from backends: a permission granted by any backend is treated as granted, unless a backend raises PermissionDenied, which stops further checking. Consequently, inspecting only the built-in permission records may not explain every effective permission in a project with custom backends.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What do the default permissions protect?

The default permissions are model-level permissions. A check such as user.has_perm("blog.change_post") answers whether the user has permission to change instances of that model according to the configured backends. It does not automatically decide whether the user may change one particular post but not another.

The default ModelBackend does not implement object-level permissions. When an object is passed to a permission lookup using this backend, it returns no permissions for that object. An application that needs row-specific rules must use an object-aware backend or another authorization implementation, then apply those rules in its own access checks.

Approach Scope Where access is enforced Maintenance consideration
Default ModelBackend Model-level permissions Application checks using Django’s permission APIs Uses Django’s built-in model permission system; it does not supply row-specific authorization
Object-aware backend or additional authorization implementation Object-level rules, if implemented by the chosen system Application checks must use that system’s object-aware behavior Requires configuring, integrating, and maintaining the additional authorization logic

Proxy models are another case to handle deliberately. They have their own content type when configured accordingly, and they do not automatically inherit the concrete model’s permissions.

Why might a permission change not appear immediately?

The default backend caches permission results on a user object after lookup. If code changes permissions and then checks them again using that same instance, the result can reflect the cached lookup rather than the change. Fetch a fresh user instance from the database before checking again; refresh_from_db() does not clear this permission cache.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What to verify in a project

  • Check the project’s Django version and migrations before assuming physical table names.
  • Confirm whether the project uses Django’s default user model or a custom user model.
  • Inspect configured authentication backends when database permission records do not explain a permission result.
  • Determine whether the application needs model-level authorization or object-level rules; the default backend covers the former, not the latter.
  • After changing permissions in code, use a newly fetched user instance when an immediate permission check must reflect the change.

For version-specific details, consult Django’s authentication system guide, auth reference, and authentication customization guide.

Best Value

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.