Django's User and Group models form the foundation of the authentication and authorization system. Understanding how to work with users, organize them into groups, and manage their relationships is crucial for implementing effective access control in your Django applications.
# Django's built-in User model
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
# Always use get_user_model() for flexibility
User = get_user_model()
class UserModelExploration:
"""Comprehensive exploration of the User model"""
@staticmethod
def user_model_fields():
"""Explore User model fields and their purposes"""
# Core identification fields
user_fields = {
'username': 'Unique identifier for login (max 150 chars)',
'email': 'Email address (not unique by default)',
'first_name': 'First name (max 150 chars)',
'last_name': 'Last name (max 150 chars)',
'password': 'Hashed password',
}
# Permission and status fields
permission_fields = {
'is_active': 'User account is active',
'is_staff': 'User can access admin site',
'is_superuser': 'User has all permissions',
}
# Timestamp fields
timestamp_fields = {
'date_joined': 'When user account was created',
'last_login': 'Last successful login timestamp',
}
return {
'user_fields': user_fields,
'permission_fields': permission_fields,
'timestamp_fields': timestamp_fields
}
@staticmethod
def create_users_examples():
"""Examples of creating different types of users"""
# Create regular user
regular_user = User.objects.create_user(
username='john_doe',
email='john@example.com',
password='secure_password123',
first_name='John',
last_name='Doe'
)
# Create staff user
staff_user = User.objects.create_user(
username='jane_staff',
email='jane@company.com',
password='staff_password123',
first_name='Jane',
last_name='Staff',
is_staff=True
)
# Create superuser
superuser = User.objects.create_superuser(
username='admin',
email='admin@company.com',
password='admin_password123',
first_name='Admin',
last_name='User'
)
return {
'regular_user': regular_user,
'staff_user': staff_user,
'superuser': superuser
}
@staticmethod
def user_methods_demonstration():
"""Demonstrate important User model methods"""
user = User.objects.create_user(
username='demo_user',
email='demo@example.com',
password='demo_password123',
first_name='Demo',
last_name='User'
)
# Authentication methods
auth_methods = {
'check_password': user.check_password('demo_password123'), # True
'has_usable_password': user.has_usable_password(), # True
'set_unusable_password': 'user.set_unusable_password()', # Disables password login
}
# Name methods
name_methods = {
'get_full_name': user.get_full_name(), # "Demo User"
'get_short_name': user.get_short_name(), # "Demo"
'get_username': user.get_username(), # "demo_user"
}
# Status properties
status_properties = {
'is_authenticated': user.is_authenticated, # True (for real users)
'is_anonymous': user.is_anonymous, # False (for real users)
'is_active': user.is_active, # True by default
'is_staff': user.is_staff, # False by default
'is_superuser': user.is_superuser, # False by default
}
return {
'auth_methods': auth_methods,
'name_methods': name_methods,
'status_properties': status_properties
}
# Advanced user management
class AdvancedUserManagement:
"""Advanced user management techniques"""
@staticmethod
def bulk_user_operations():
"""Perform bulk operations on users"""
# Bulk create users
users_data = [
{'username': f'user_{i}', 'email': f'user{i}@example.com', 'password': 'temp_password'}
for i in range(1, 101)
]
users_to_create = []
for user_data in users_data:
user = User(
username=user_data['username'],
email=user_data['email']
)
user.set_password(user_data['password'])
users_to_create.append(user)
# Bulk create (more efficient than individual creates)
created_users = User.objects.bulk_create(users_to_create)
# Bulk update users
User.objects.filter(username__startswith='user_').update(
is_active=True,
first_name='Bulk',
last_name='User'
)
# Bulk delete inactive users
deleted_count = User.objects.filter(
is_active=False,
last_login__isnull=True,
date_joined__lt=timezone.now() - timedelta(days=30)
).delete()
return {
'created_count': len(created_users),
'deleted_count': deleted_count[0] if deleted_count else 0
}
@staticmethod
def user_filtering_and_queries():
"""Advanced user filtering and queries"""
from django.db.models import Q, Count, Max, Min
from datetime import timedelta
# Active users who logged in recently
recent_active_users = User.objects.filter(
is_active=True,
last_login__gte=timezone.now() - timedelta(days=7)
)
# Users with specific permissions
users_with_add_permission = User.objects.filter(
Q(user_permissions__codename='add_post') |
Q(groups__permissions__codename='add_post')
).distinct()
# Staff users without superuser privileges
staff_non_super = User.objects.filter(
is_staff=True,
is_superuser=False
)
# Users by registration period
new_users = User.objects.filter(
date_joined__gte=timezone.now() - timedelta(days=30)
)
# Users with email domains
company_users = User.objects.filter(
email__endswith='@company.com'
)
# Complex queries with annotations
user_stats = User.objects.annotate(
group_count=Count('groups'),
permission_count=Count('user_permissions')
).filter(
group_count__gt=0
)
return {
'recent_active': recent_active_users.count(),
'with_add_permission': users_with_add_permission.count(),
'staff_non_super': staff_non_super.count(),
'new_users': new_users.count(),
'company_users': company_users.count(),
'users_with_groups': user_stats.count()
}
@staticmethod
def user_profile_management():
"""Manage user profiles and extended information"""
# Example user profile model
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True)
phone_number = models.CharField(max_length=15, blank=True)
website = models.URLField(blank=True)
# Preferences
email_notifications = models.BooleanField(default=True)
theme_preference = models.CharField(
max_length=10,
choices=[('light', 'Light'), ('dark', 'Dark')],
default='light'
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.user.username}'s Profile"
def get_age(self):
if self.birth_date:
today = timezone.now().date()
return today.year - self.birth_date.year - (
(today.month, today.day) < (self.birth_date.month, self.birth_date.day)
)
return None
# Signal to create profile automatically
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
if hasattr(instance, 'profile'):
instance.profile.save()
return UserProfile
# Django's Group model for organizing users
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
class GroupManagement:
"""Comprehensive group management"""
@staticmethod
def create_groups_with_permissions():
"""Create groups and assign permissions"""
# Create groups for different user roles
groups_config = {
'Editors': [
'add_post', 'change_post', 'delete_post', 'view_post',
'add_category', 'change_category', 'view_category'
],
'Moderators': [
'change_post', 'delete_post', 'view_post',
'add_comment', 'change_comment', 'delete_comment', 'view_comment'
],
'Authors': [
'add_post', 'change_post', 'view_post'
],
'Subscribers': [
'view_post', 'add_comment', 'change_comment'
]
}
created_groups = {}
for group_name, permission_codenames in groups_config.items():
# Create or get group
group, created = Group.objects.get_or_create(name=group_name)
# Get permissions
permissions = Permission.objects.filter(
codename__in=permission_codenames
)
# Assign permissions to group
group.permissions.set(permissions)
created_groups[group_name] = {
'group': group,
'created': created,
'permissions_count': permissions.count()
}
return created_groups
@staticmethod
def manage_group_membership():
"""Manage users in groups"""
# Get groups
editors_group = Group.objects.get(name='Editors')
authors_group = Group.objects.get(name='Authors')
# Add users to groups
editor_users = User.objects.filter(is_staff=True, is_superuser=False)
for user in editor_users:
user.groups.add(editors_group)
# Add specific users to authors group
author_usernames = ['john_doe', 'jane_author', 'bob_writer']
author_users = User.objects.filter(username__in=author_usernames)
authors_group.user_set.add(*author_users)
# Remove users from group
inactive_users = User.objects.filter(is_active=False)
for group in Group.objects.all():
group.user_set.remove(*inactive_users)
return {
'editors_count': editors_group.user_set.count(),
'authors_count': authors_group.user_set.count()
}
@staticmethod
def group_hierarchy_simulation():
"""Simulate group hierarchy with custom logic"""
# Define group hierarchy
group_hierarchy = {
'Administrators': {
'level': 1,
'inherits_from': [],
'permissions': ['*'] # All permissions
},
'Managers': {
'level': 2,
'inherits_from': ['Editors', 'Moderators'],
'permissions': ['manage_users', 'view_reports']
},
'Editors': {
'level': 3,
'inherits_from': ['Authors'],
'permissions': ['edit_any_post', 'publish_post']
},
'Authors': {
'level': 4,
'inherits_from': ['Subscribers'],
'permissions': ['create_post', 'edit_own_post']
},
'Subscribers': {
'level': 5,
'inherits_from': [],
'permissions': ['view_content', 'comment']
}
}
def get_effective_permissions(user):
"""Get all effective permissions for user including inherited"""
effective_permissions = set()
user_groups = user.groups.all()
for group in user_groups:
# Add direct group permissions
group_perms = group.permissions.all()
effective_permissions.update(perm.codename for perm in group_perms)
# Add inherited permissions
if group.name in group_hierarchy:
inherits_from = group_hierarchy[group.name]['inherits_from']
for parent_group_name in inherits_from:
try:
parent_group = Group.objects.get(name=parent_group_name)
parent_perms = parent_group.permissions.all()
effective_permissions.update(perm.codename for perm in parent_perms)
except Group.DoesNotExist:
continue
return effective_permissions
return get_effective_permissions
@staticmethod
def dynamic_group_assignment():
"""Dynamically assign users to groups based on criteria"""
def auto_assign_groups():
"""Automatically assign users to appropriate groups"""
# Get groups
try:
editors_group = Group.objects.get(name='Editors')
authors_group = Group.objects.get(name='Authors')
subscribers_group = Group.objects.get(name='Subscribers')
except Group.DoesNotExist:
return "Groups not found"
# Auto-assign based on user attributes
for user in User.objects.filter(is_active=True):
# Staff users become editors
if user.is_staff and not user.is_superuser:
user.groups.add(editors_group)
# Users with posts become authors
elif hasattr(user, 'posts') and user.posts.exists():
user.groups.add(authors_group)
# All other active users are subscribers
else:
user.groups.add(subscribers_group)
return "Auto-assignment completed"
def assign_based_on_activity():
"""Assign groups based on user activity"""
from django.db.models import Count
# Users with many posts become editors
prolific_users = User.objects.annotate(
post_count=Count('posts')
).filter(post_count__gte=10)
editors_group = Group.objects.get(name='Editors')
for user in prolific_users:
user.groups.add(editors_group)
# Users with recent activity remain active
recent_users = User.objects.filter(
last_login__gte=timezone.now() - timedelta(days=30)
)
# Remove inactive users from all groups
inactive_users = User.objects.exclude(
id__in=recent_users.values_list('id', flat=True)
)
for user in inactive_users:
user.groups.clear()
return auto_assign_groups, assign_based_on_activity
# Advanced group queries and operations
class AdvancedGroupOperations:
"""Advanced operations with groups"""
@staticmethod
def group_analytics():
"""Analyze group membership and permissions"""
from django.db.models import Count, Q
# Group membership statistics
group_stats = Group.objects.annotate(
user_count=Count('user'),
permission_count=Count('permissions')
).order_by('-user_count')
# Users with multiple groups
multi_group_users = User.objects.annotate(
group_count=Count('groups')
).filter(group_count__gt=1)
# Groups with specific permissions
groups_with_add_perms = Group.objects.filter(
permissions__codename__startswith='add_'
).distinct()
# Orphaned permissions (not assigned to any group)
orphaned_permissions = Permission.objects.filter(
group__isnull=True,
user__isnull=True
)
analytics = {
'total_groups': Group.objects.count(),
'groups_with_users': group_stats.filter(user_count__gt=0).count(),
'multi_group_users': multi_group_users.count(),
'groups_with_add_perms': groups_with_add_perms.count(),
'orphaned_permissions': orphaned_permissions.count(),
'group_details': [
{
'name': group.name,
'user_count': group.user_count,
'permission_count': group.permission_count
}
for group in group_stats
]
}
return analytics
@staticmethod
def group_permission_matrix():
"""Create a permission matrix for all groups"""
groups = Group.objects.prefetch_related('permissions').all()
all_permissions = Permission.objects.all().order_by('content_type__app_label', 'codename')
matrix = {}
for group in groups:
group_permissions = set(group.permissions.values_list('id', flat=True))
matrix[group.name] = {}
for permission in all_permissions:
matrix[group.name][f"{permission.content_type.app_label}.{permission.codename}"] = (
permission.id in group_permissions
)
return matrix
@staticmethod
def cleanup_groups():
"""Clean up unused groups and optimize group structure"""
cleanup_results = {
'empty_groups_removed': 0,
'duplicate_permissions_cleaned': 0,
'inactive_users_removed': 0
}
# Remove empty groups (no users and no permissions)
empty_groups = Group.objects.annotate(
user_count=Count('user'),
permission_count=Count('permissions')
).filter(user_count=0, permission_count=0)
cleanup_results['empty_groups_removed'] = empty_groups.count()
empty_groups.delete()
# Remove inactive users from all groups
inactive_users = User.objects.filter(is_active=False)
for user in inactive_users:
removed_count = user.groups.count()
user.groups.clear()
cleanup_results['inactive_users_removed'] += removed_count
# Clean up duplicate permissions in groups
for group in Group.objects.all():
permissions = list(group.permissions.all())
unique_permissions = list(set(permissions))
if len(permissions) != len(unique_permissions):
group.permissions.set(unique_permissions)
cleanup_results['duplicate_permissions_cleaned'] += (
len(permissions) - len(unique_permissions)
)
return cleanup_results
# Group-based access control
class GroupBasedAccessControl:
"""Implement group-based access control patterns"""
@staticmethod
def group_required_decorator():
"""Decorator to require specific group membership"""
from functools import wraps
from django.core.exceptions import PermissionDenied
def group_required(*group_names):
def decorator(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
if not request.user.is_authenticated:
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(request.get_full_path())
user_groups = request.user.groups.values_list('name', flat=True)
if not any(group in user_groups for group in group_names):
raise PermissionDenied(
f"Access denied. Required groups: {', '.join(group_names)}"
)
return view_func(request, *args, **kwargs)
return wrapper
return decorator
return group_required
@staticmethod
def group_based_queryset_filtering():
"""Filter querysets based on user's group membership"""
def get_filtered_queryset(user, model_class):
"""Get queryset filtered by user's group permissions"""
if user.is_superuser:
return model_class.objects.all()
user_groups = user.groups.values_list('name', flat=True)
# Define group-based filtering rules
if 'Administrators' in user_groups:
return model_class.objects.all()
elif 'Editors' in user_groups:
# Editors can see all published content and their own drafts
return model_class.objects.filter(
Q(status='published') | Q(author=user)
)
elif 'Authors' in user_groups:
# Authors can only see their own content
return model_class.objects.filter(author=user)
else:
# Default: only published content
return model_class.objects.filter(status='published')
return get_filtered_queryset
@staticmethod
def hierarchical_group_permissions():
"""Implement hierarchical group permissions"""
def user_can_access_group_level(user, required_level):
"""Check if user has access to a specific group level"""
group_levels = {
'Administrators': 1,
'Managers': 2,
'Editors': 3,
'Authors': 4,
'Subscribers': 5
}
user_groups = user.groups.values_list('name', flat=True)
user_level = min(
[group_levels.get(group, 999) for group in user_groups],
default=999
)
return user_level <= required_level
def get_accessible_content(user):
"""Get content accessible to user based on group hierarchy"""
user_groups = user.groups.values_list('name', flat=True)
# Define content access levels
if any(group in ['Administrators', 'Managers'] for group in user_groups):
access_level = 'all'
elif 'Editors' in user_groups:
access_level = 'editorial'
elif 'Authors' in user_groups:
access_level = 'authoring'
else:
access_level = 'public'
return access_level
return user_can_access_group_level, get_accessible_content
Understanding Users and Groups in Django enables you to build sophisticated access control systems. By properly organizing users into groups and managing their permissions, you can create scalable authorization schemes that grow with your application's complexity.
Overview of Django's Authentication System
Django's authentication system is a comprehensive framework that handles user authentication, authorization, and session management out of the box. Understanding its architecture, components, and workflow is essential for building secure Django applications.
Permissions
Django's permission system provides fine-grained access control for your application's resources. Understanding how to create, assign, and check permissions enables you to build secure applications with precise authorization controls.