As a developer, working on various projects for clients across the USA, one common requirement I often encounter is creating a user profile system. Whether you’re building a social platform, an e-commerce site, or a membership portal, having a customized user profile is essential.
Django’s built-in User model covers basic authentication and user management. In this tutorial, I’ll walk you through how to create a user profile system in Django that is flexible, scalable, and easy to maintain.
I’ll share two common methods: extending the built-in User model with a OneToOne linked profile model, and customizing the User model itself. Both methods have their use cases, and I’ll help you decide which one suits your needs best.
Let’s get in!
Method 1: Extend Django’s User Model with a Profile Model
This is the most popular and recommended approach. Instead of modifying Django’s built-in User model, you create a separate profile model that links to the User model via a OneToOne relationship. This keeps the authentication system intact and allows you to add any custom fields you want.
Check out Outputting Python to HTML in Django
Step 1: Create a New Django App
First, create a new app for user profiles:
python manage.py startapp accountsAdd 'accounts' to your INSTALLED_APPS in settings.py.
Step 2: Define the Profile Model
In accounts/models.py, add:
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=20, blank=True)
address = models.TextField(blank=True)
city = models.CharField(max_length=100, blank=True)
state = models.CharField(max_length=100, blank=True)
zip_code = models.CharField(max_length=10, blank=True)
profile_picture = models.ImageField(upload_to='profile_pics/', blank=True, null=True)
def __str__(self):
return f"{self.user.username}'s Profile"This model stores additional information about the user, such as phone number and address, which are common in US-based applications.
Step 3: Automatically Create or Update Profile
To make sure a profile is created whenever a new user is registered, use Django signals. In accounts/signals.py:
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()Then, import this signal in accounts/apps.py:
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
def ready(self):
import accounts.signalsMake sure your app config is set correctly in settings.py:
INSTALLED_APPS = [
# other apps
'accounts.apps.AccountsConfig',
]Step 4: Create Forms for User and Profile Update
In accounts/forms.py:
from django import forms
from django.contrib.auth.models import User
from .models import Profile
class UserUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['phone_number', 'address', 'city', 'state', 'zip_code', 'profile_picture']Step 5: Create Views to Handle Profile Display and Update
In accounts/views.py:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import UserUpdateForm, ProfileUpdateForm
from django.contrib import messages
@login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, 'Your profile has been updated!')
return redirect('profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request, 'accounts/profile.html', context)Read Change Django Version in Python
Step 6: Create Templates
Create a template accounts/templates/accounts/profile.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
<h2>Profile</h2>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ u_form.as_p }}
{{ p_form.as_p }}
<button type="submit">Update</button>
</form>
{% endblock %}Step 7: Configure URLs
In accounts/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('profile/', views.profile, name='profile'),
]Include this in your project’s main urls.py:
from django.urls import path, include
urlpatterns = [
# other paths
path('accounts/', include('accounts.urls')),
]Step 8: Set Up Media Handling for Profile Pictures
In your project’s settings.py:
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'In the main urls.py add:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)You can refer to the screenshot below to see the output.

Check out Django vs ReactJS
Method 2: Substitute the Default User Model (Custom User Model)
If you want to have full control over the user model, including authentication fields, you can create a custom user model from scratch. This method is more advanced but necessary if you want to change the username field or add required fields at the user level.
Step 1: Create a Custom User Model
In accounts/models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
phone_number = models.CharField(max_length=20, blank=True)
address = models.TextField(blank=True)
city = models.CharField(max_length=100, blank=True)
state = models.CharField(max_length=100, blank=True)
zip_code = models.CharField(max_length=10, blank=True)
profile_picture = models.ImageField(upload_to='profile_pics/', blank=True, null=True)Step 2: Update Settings to Use Custom User
In settings.py:
AUTH_USER_MODEL = 'accounts.CustomUser'Step 3: Update Forms and Admin
You’ll need to customize the user creation and change forms, and register your custom user in the admin panel.
Due to complexity, this method is recommended only if you’re starting a new project.
You can refer to the screenshot below to see the output.


Read Upload Image File in Django
Conclusion
Creating a user profile system in Django is easy once you understand the best approach for your project. Extending the built-in User model with a profile model is usually the safest and easiest way to add custom user information without breaking authentication.
I’ve found that keeping authentication separate from user data helps maintain the integrity of the system and makes future upgrades easier. Adding profile pictures and address fields is common for US-based applications, so this tutorial covers those practical needs.
If you want more control over the user fields and authentication, consider the custom user model method, but be aware that it requires more setup and careful planning.
I hope this guide helps you build a clean and effective user profile system in your Django projects.
You may also read:
- ModuleNotFoundError: No module named Django
- How to View Uploaded Files in Django
- Python Django: Get Admin Password

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.