Extending Django Built-In User Model With One-To-One Field

Feb. 1, 2023, 9:52 p.m.

django python

Django have many built-in features. One of them is an authentication system which allow us to create user, handle their permissions and  allow them to create a login sessions. Django authentication system have its User model. This User model store information of user like username, password, email, name etc. Django authentication system also allow to create an anonymous sessions.

As User model is base model which have only important functionality, sometimes we need to extends its functionality to store some extra information like profile pic, phone etc.

Here's some steps to extend the default user model in Django, you can create a new model that has a one-to-one relationship with the Django User model. This allows you to add additional fields to store additional information about the user. Here's a high-level overview of the steps involved in extending the user model:

Quick Setup

If you haven't install python and django you can start from here Installing python and django

Create a virtual environment

python -m venv env

Activate virtual environment

source env/bin/activate

Installing Django

Install python using pip command
pip install django

Creating your first Project

django-admin startproject projectname

Creating your first App

Change to project directory: "cd projectname"

django-admin startapp appname

you see app have its own file structure, hence it is independent of the project. To work with app we need to include it in project

projectname/projectname/settings.py

# Application definition
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "whitenoise.runserver_nostatic",
    "django.contrib.sitemaps",
    "appname", # <-- add this 
]

Create Profile Model

Here we create a Profile model which extends User model with one-to-one field

projectname/appname/models.py

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone = models.Charfield(max_length=10)
    profile_pic = models.ImageField(
        upload_to='profile/')

    def __str__(self):
        return self.user.username

After Creating Profile model we need run some command to make changes into our database.

python manage.py makemigrations

This command is responsible for creating new migrations based on the changes you have made to your models.

python manage.py migrate

Above command is responsible for applying and unapplying migrations. This command actually change the database schema.

Signals for automate Profile instance

This is good as we can store some extra information about the user we created with User model, But all this work is manual, means we need to manually attach a User instance to Profile instance, which is sometimes not practical. But Django provide a solution to this issue.

We can signals which is also a built-in feature in django, allow to decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place.

projectname/appname/models.py

from django.db import models
from django.contrib.auth.models import User

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.exceptions import ObjectDoesNotExist

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone = models.Charfield(max_length=10)
    profile_pic = models.ImageField(
        upload_to='profile/')

    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

This automate the process of creating Profile instance when a User instance is created.

Access Profile model data

This is pretty simple how you can access data the of Profile model from User model instance

user.profile.phone

Inside Template

<h2>{{ user.get_full_name }}</h2>
<p>Username: {{ user.username }}</p>
<p>phone: {{ user.profile.phone }}</p>
<img src="{{ user.profile.profile_pic.url }}" alt="profile pic" width="200" height="200">

Update Profile instance

def update_profile(request, user_id):
    user = User.objects.get(pk=user_id)
    user.profile.phone = "9898989898"
    user.save()
author image

bracketcoders

A learing portal for your coding interest.

View Profile