In this Python tutorial, I will show you how to create a user profile using Django. Basically, you will understand how to create a user with a profile in Django.
So in this tutorial, first I will show you how to design the user home page with a logo, navigation menu, and login and register menu. Then I show you how to create a profile page for the user.
Also, you will learn how to design the page and implement the functionality to show the drop-down menu whenever the user clicks on the profile picture. You will be able to update the user profile information.
How to Create a User Profile Using Django
Setting the virtual environment for the Django Project by following the below commands.
First, create a virtual environment ‘profile_env’ using the below command.
python -m venv profile_env
Activate the created env using the below code.
profile_env\Scripts\activate
After activating the env, install the Django using the below code.
pip install Django
Create a Django project ‘userprofile’ by executing the below command.
django-admin startproject userprofile .
Then create the Django app ‘profile_app’ using the below command.
django-admin startapp profile_app
After this, you continue with your terminal or command prompt or you can use any IDE (Visual Studio Code).
Register the app ‘profile_app’ in the INSTALLED_APP section of the setting.py file of your Django project ‘userprofile’.
Run the below command in your terminal to migrate all the default models that comes with Django.
python manage.py migrate
Open the views.py file of your Django app ‘profile_app’ and create the view ‘Home’ and add the following code.
from django.shortcuts import render
from django.views import View
class HomeView(View):
def get(self, request):
return render(request,'home.html')
Create a new folder ‘templates’ in your Django app ‘profile_app’ and in that folder, create a new HTML file called ‘home.html’. Leave this file empty for now.
Now let’s define the URLs for the app, so create a new file ‘urls.py’ in your app and add the following line.
from django.urls import path
from .views import HomeView
urlpatterns = [
path('', HomeView.as_view(), name='home-page'),
]
Also, set the URLs of the Django project ‘userprofile’ by opening the file ‘urls.py’ and adding the following lines.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('profile_app.urls'))
]
Let’s set up the project for the static files, so create a new folder ‘static’ at your Django project level. In that folder create two new folders ‘css’ and ‘js’.
Open the setting.py file of your Django project and add the following code.
import os
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
After the configuration of the static files and folder, create a new model ‘Profiles’ in the models.py of your Django app ‘profile_app’ and add the following code.
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
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=50, null= True)
designation = models.CharField(max_length=100, null= True)
mobile_number = models.CharField(max_length=20, null=True)
profile_image = models.ImageField(null=True, upload_to='static/images/' )
profile_summary = models.TextField(max_length=300, null= True)
city = models.CharField(max_length=100, null= True)
state = models.CharField(max_length=100, null= True)
country = models.CharField(max_length=100, null= True)
@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()
In the above code, create the model ‘Profile’ to store the profile information of the user. Look at line 8, where the field user defines the one-to-one relationship with the ‘User’ model and this ‘User’ model is built into the Django model.
Next, the receiver function ‘create_user_profile’ is a signal, whenever a new user instance is created at the same time a new profile instance is created which is associated with that user.
Then again, the receiver function ‘save_user_profile’, and this signal saves the associated Profile instance with the user.
If you don’t know how signal work in Django, then you can refer to the tutorial How to Create Signal in Django
Then register this model in the file admin.py of your Django app ‘profile_app’ by adding the following code.
from django.contrib import admin
from .models import Profile
admin.site.register(Profile)
Now use the below command one by one to migrate the model into the database.
pip install pillow
python manage.py makemigrations
python manage.py migrate
After migrating the model, create an admin user by following the below command.
python manage.py createsuperuser
Then enter the required details into the command prompt or terminal to create a superuser.
After creating the admin superuser, remember you have created the template file ‘home.html’ in the folder ‘templates’ of your app ‘profile_app’, now in that file add the following code.
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<link rel="stylesheet" href="{%static 'css/home.css' %}">
</head>
<body>
<div class="header">
<nav>
<img src="{%static 'images/logo.png'%}" alt="" class="logo">
<ul>
<li><a href="{%url 'home-page'%}">Home</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
{% if user.is_authenticated %}
{% if request.user.profile.profile_image %}
<img src="{{ request.user.profile.profile_image.url}}" alt="" class="profile-user-pic"
onclick="toggleMenu()">
{% else %}
<img src="{% static 'images/mypic.png' %}" alt="Default Image" class="profile-user-pic"
onclick="toggleMenu()">
{% endif %}
<div class="profile-sub-menu-wrap" id="profile-subMenu">
<div class="profile-sub-menu">
<div class="profile-user-info">
{% if request.user.profile.profile_image %}
<img src="{{ request.user.profile.profile_image.url}}" alt="">
{% else %}
<img src="{% static 'images/mypic.png' %}" alt="Default Image">
{% endif %}
<h3>{{ request.user.profile.full_name }}</h3>
<h5>{{ request.user.profile.designation }}</h5>
</div>
<hr>
<a href="{%url 'user-profile'%}" class="profile-sub-menu-link">
<img src="{% static 'images/profile.png' %}">
</img>
<p>Edit Profile</p>
</a>
<a href="" class="profile-sub-menu-link">
<img src="{% static 'images/setting.png' %}">
</img>
<p>Setting & Privacy</p>
</a>
<a href="" class="profile-sub-menu-link">
<img src="{% static 'images/help.png' %}">
</img>
<p>Help & Support</p>
</a>
<a href="{%url 'logout'%}" class="profile-sub-menu-link">
<img src="{% static 'images/logout.png' %}">
</img>
<p>Logout</p>
</a>
</div>
</div>
{% else %}
<div class="register-login-menu">
<a href="{% url 'login' %}" class="menu-link">Login</a>
<span class="menu-separator">|</span>
<a href="{% url 'register' %}" class="menu-link">Register</a>
</div>
{% endif %}
</nav>
{% block content %}
{% endblock %}
</div>
<script src="{% static 'js/script.js' %}"></script>
</body>
</html>
The above code is the front-end part of the Django profile application, and this defines the layout of the website home page.
The first code {% load static %} and this code loads the static files like CSS, images, and Javascript from the directory static that you have created in your Django project.
Then img with source from {% static ‘images/logo.png’ %} displays the website’s logo. After this look at the code {% if user.is_authenticated %} at line 22, this code checks if the user is logged in or authenticated.
- If the user is logged in, then it displays the user profile picture if exists using the {% if request.user.profile.profile_image %}, otherwise it displays the default image.
- if the user is not authenticated, then it shows the login and register menu in place of the user profile picture.
When any user clicks on the profile picture, it triggers the Javascript function called toggleMenu() which shows the drop-down menu containing the user information such as name, image, designation, and some options.
The Javascript function toggleMenu() will be defined later in the tutorial.
Then create a new file called ‘home.css’ in the CSS folder of the static file and add the following code to that file.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Popins', sans-serif;
}
.header {
width: 100%;
min-height: 100vh;
background: #4477CE;
color: #525252;
}
nav {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 10%;
background: #1a1a1a1a;
position: relative;
}
.logo {
width: 120px;
}
.profile-user-pic {
width: 40px;
border-radius: 50%;
cursor: pointer;
margin-left: 30px;
}
nav ul {
width: 100%;
text-align: center;
}
nav ul li {
display: inline-block;
list-style: none;
margin: 10px 20px;
}
nav ul li a {
color: #fff;
text-decoration: none;
}
.profile-sub-menu-wrap {
position: absolute;
top: 100%;
right: 10%;
width: 320px;
max-height: 0px;
overflow: hidden;
transition: max-height 0.5s;
}
.profile-sub-menu-wrap.open-menu {
max-height: 400px;
}
.profile-sub-menu {
background: #8CABFF;
padding: 20px;
margin: 10px;
border-radius: 5px;
}
.profile-user-info {
display: flex;
align-items: center;
position: relative;
}
.profile-user-info h3 {
font-weight: 500;
}
.profile-user-info h5 {
font-weight: 500;
top: 65%;
position: absolute;
left: 29%;
}
.profile-user-info img {
width: 60px;
border-radius: 50%;
margin-right: 15px;
}
.profile-sub-menu hr {
border: 0;
height: 1px;
background: #ccc;
margin: 15px 0 10px;
}
.profile-sub-menu-link img {
width: 24px;
height: 24px;
background-color: #e5e5e5;
border-radius: 50%;
margin-right: 15px;
}
.profile-sub-menu-link {
display: flex;
align-items: center;
text-decoration: none;
color: #525252;
margin: 12px 0;
}
.profile-sub-menu-link p {
width: 100%;
}
.register-login-menu {
display: flex;
align-items: center;
background-color: #4477CE;
border-radius: 5px;
padding: 5px 10px;
}
.menu-link {
text-decoration: none;
color: #fff;
font-weight: bold;
margin: 0 10px;
padding: 5px 10px;
border-radius: 3px;
transition: background-color 0.3s;
}
.menu-link:hover {
background-color: #365a9c;
color: #fff;
}
.menu-separator {
margin: 0 5px;
color: #fff;
}
Also, create the file ‘script.js’ in the js folder of static and add the following code in that file.
let subMenu = document.getElementById("profile-subMenu")
function toggleMenu() {
subMenu.classList.toggle("open-menu")
}
The above is the Javascript code that accesses the element with an id equal to ‘profile-subMenu’, then it stores the reference to that element in a variable called subMenu and then the function toggleMenu() is defined which uses the function classList.toggle(“open-menu”) on the element subMenu.
The function changes the CSS presence of the class named ‘open_menu’ on the ‘subMenu’ element.
Now, we also need the functionality of user register, log in, and logout, so the first user will register with username and password after that user will log in and can edit or update the profile.
First, create a form for registering the user, so create a file called ‘forms.py’ in your Django app ‘profile_app’ and add the following code in that file.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]
Then create views for the user to register, log in, and log out into the views.py file of the Django app ‘profile_app’, So add the following code.
from django.views import View
from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate, logout
from .forms import RegisterForm
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
user = form.save()
return redirect('login')
else:
form = RegisterForm()
return render(request, 'register.html', {'form': form})
def user_login(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('home-page')
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
form = AuthenticationForm()
return render(request, 'login.html', {'form': form})
def user_logout(request):
logout(request)
return redirect('login')
The above code defines the view for user registration, login, and logout. if you don’t know how the login system works in Django, then refer to the tutorial Login system in Python Django.
Also, create the new HTML files ‘register.html’ and ‘login.html’ and add the following code to these files.
In the register.html file add the following code.
{% extends "home.html" %}
{% block content %}
<div style="max-width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ccc; border-radius: 5px;">
<h2 style="text-align: center;">Register</h2>
<form method="post" style="display: flex; flex-direction: column;">
{% csrf_token %}
{{ form.username.label_tag }} <br>
{{ form.username }} <br><br>
{{ form.email.label_tag }} <br>
{{ form.email }} <br><br>
{{ form.password1.label_tag }} <br>
{{ form.password1 }} <br><br>
{{ form.password2.label_tag }} <br>
{{ form.password2 }} <br><br>
<button type="submit"
style="padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;">Register</button>
</form>
</div>
{% endblock %}
In the login.html add the following code.
{% extends "home.html" %}
{% block content %}
<div style="max-width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ccc; border-radius: 5px;">
<h2 style="text-align: center;">Login</h2>
<form method="post" style="display: flex; flex-direction: column;">
{% csrf_token %}
{{ form.username.label_tag }} <br>
{{ form.username }} <br><br>
{{ form.password.label_tag }} <br>
{{ form.password }} <br><br>
<button type="submit" style="padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;">Login</button>
</form>
</div>
{% endblock %}
Also, create the view ‘UserProfile’ in the file views.py which will show and update the user profile, so add the following code.
from .models import Profile
from django.core.files.base import ContentFile
class UserProfile(View):
template_name = 'profile.html'
def get(self, request):
try:
user_profile = Profile.objects.get(user=request.user)
except Profile.DoesNotExist:
user_profile = None
form_data = {
'name': user_profile.full_name if user_profile else '',
'email': request.user.email if user_profile else '',
'designation': user_profile.designation if user_profile else '',
'mobile_no': user_profile.mobile_number if user_profile else '',
'profile_image': user_profile.profile_image if user_profile else '',
'profile_summary': user_profile.profile_summary if user_profile else '',
'city': user_profile.city if user_profile else '',
'state': user_profile.state if user_profile else '',
'country': user_profile.country if user_profile else '',
}
context = {
'profile': user_profile,
'form_data': form_data
}
return render(request, self.template_name, context)
def post(self, request):
try:
user_profile = Profile.objects.get(user=request.user)
except Profile.DoesNotExist:
user_profile = None
uploaded_image = request.FILES.get('profile_image', None)
if uploaded_image:
user_profile.profile_image.save(uploaded_image.name, ContentFile(uploaded_image.read()))
full_name = request.POST.get('name')
email = request.POST.get('email')
designation = request.POST.get('designation')
mobile_number = request.POST.get('mobile_no')
profile_summary = request.POST.get('profile_summary')
city = request.POST.get('city')
state = request.POST.get('state')
country = request.POST.get('country')
if user_profile:
user_profile.full_name = full_name
user_profile.designation = designation
user_profile.mobile_number = mobile_number
user_profile.profile_summary = profile_summary
user_profile.city = city
user_profile.state = state
user_profile.country = country
user_profile.save()
user_profile.user.email = email
user_profile.user.save()
return redirect('user-profile')
In the above code, the get() method handles the GET requests to get and display the user information. In simple words, it gets the logged-in user profile data from the database using the code user_profile = Profile.objects.get(user=request.user).
- The new dictionary named form_data is created, and this form_data contains the initial value for the form which appears on the profile page of the user.
- In this form, the initial value is the data of the logged-in user, if the data is available which is related to a specific field such as the user’s full name, email and etc in the database, then that value is assigned to a specific variable otherwise an empty string is assigned.
Then form_data is passed as context to the template ‘profile.html’
Similarly, the post() method handles the POST request and retrieves the user information from the form which is filled in by the user on the profile page.
- It takes the uploaded image by the user using the code user_profile.profile_image.save(uploaded_image.name, ContentFile(uploaded_image.read())) from the request.FILES dictionary and saves it to the user’s profile image field.
- Then other user details such as name, email, and designation are collected using the request.POST dictionary.
Then updates the user’s profile fields with the collected data and saves the changes to the profile and the associated user’s email.
Create the template ‘profile.html’ file in the templates folder of your Django app ‘profile_app’ for the view and add the following code in that file.
{% extends 'home.html' %}
{% load static %}
{% block content %}
<link rel="stylesheet" href="{%static 'css/profile.css' %}">
<div class="profile-page">
<div class="profile-container">
<div class="profile-container-pic">
{% if request.user.profile.profile_image %}
<img src="{{ request.user.profile.profile_image.url}}" alt="Profile Image">
{% else %}
<img src="{% static 'images/mypic.png' %}" alt="Default Image">
{% endif %}
</div>
<div class="profile-details">
<h3>{{ request.user.profile.full_name }}</h3>
<h5>{{ request.user.profile.designation }}</h5>
<hr>
<div class="text">
<div class="mobile">
<img src="{% static 'images/phone.png' %}" alt="">
<h5>{{ request.user.profile.mobile_number }}</h5>
</div>
<div class="email">
<img src="{% static 'images/email.png' %}" alt="">
<h5>{{ request.user.email }}</h5>
</div>
<div class="home">
<img src="{% static 'images/house.png' %}" alt="">
<h5>{{ request.user.profile.city }}, {{ request.user.profile.state }},
{{request.user.profile.country }}</h5>
</div>
</div>
</div>
</div>
</div>
<div class="profile-form">
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %}
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="{{ form_data.name }}" required>
<label for="designation">Designation:</label>
<input type="text" id="designation" name="designation" value="{{ form_data.designation }}" required>
<label for="mobile_no">Mobile Number:</label>
<input type="text" id="mobile_no" name="mobile_no" value="{{ form_data.mobile_no }}" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="{{ form_data.email }}" required>
<label for="profile_image">Profile Image:</label>
<input type="file" id="profile_image" name="profile_image">
<label for="profile_summary">Profile Summary:</label>
<textarea id="profile_summary" name="profile_summary" rows="4"
required>{{ form_data.profile_summary }}</textarea>
<label for="city">City:</label>
<input type="text" id="city" name="city" value="{{ form_data.city }}" required>
<label for="state">State:</label>
<input type="text" id="state" name="state" value="{{ form_data.state }}" required>
<label for="country">Country:</label>
<input type="text" id="country" name="country" value="{{ form_data.country }}" required>
<button type="submit">Submit</button>
</form>
</div>
{% endblock content %}
Specify the URL path for the register, login, logout, and profile views, so open the ‘urls.py’ file of your Django app ‘profile_app’ and add the following URLs.
from .views import HomeView, UserProfile, register, user_login, user_logout
path('profile/', UserProfile.as_view(), name='user-profile' ),
path('register/', register, name='register'),
path('login/', user_login, name='login'),
path('logout/', user_logout, name='logout'),
After specifying URLs, also add the styling for the profile page, so that create a new file called ‘profile.css’ in the CSS folder of the static folder and add the following styling code.
.profile-page{
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding-top: 20px;
}
.profile-container{
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
width: 500px;
height: 200px;
border-radius: 20px;
box-shadow: 0 6px 12px rgba(30,10,58,.04);
}
.profile-container-pic{
margin-left: 60px;
}
.profile-container-pic img{
width:100px;
height:100px
}
.profile-details{
width: 200px;
height:150px;
margin-left: 100px;
margin-right: 100px;
}
.profile-details hr{
border: 0;
height: 1px;
background:#ccc;
margin: 15px 0 10px;
}
.mobile{
display: flex;
flex-direction: row;
justify-content: space-between;
width: max-content;
margin-top: 5px;
}
.mobile img {
margin-right: 5px;
}
.email{
display: flex;
flex-direction: row;
justify-content: space-between;
width: max-content;
margin-top: 5px;
}
.email img {
margin-right: 5px;
}
.home{
display: flex;
flex-direction: row;
justify-content: space-between;
width: max-content;
margin-top: 5px;
}
.home img {
margin-right: 5px;
}
.profile-form {
width: 500px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.profile-form label {
display: block;
margin-bottom: 10px;
color: black;
}
.profile-form input[type="text"], .profile-form input[type="email"], .profile-form input[type="file"] {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.profile-form textarea {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
resize: vertical;
}
.profile-form button {
padding: 10px 15px;
background-color: #007BFF;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
.profile-form button:hover {
background-color: #0056b3;
}
Also, you will need some of the icons like email, phone and etc, so for that create a new folder ‘images’ under the static folder and download the file images and add the icons to the images folder of the static folder.
Next, add the media URL path in the setting.py file of your Django project ‘userprofile’ for that add the following line of code.
MEDIA_URL ='/images/'
After adding the icons to the folder images, your static folder structure should be like this.
Also, add the following setting into ‘urls.py’ of your Django app ‘profile_app’.
from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
After adding icons, now your project is ready, so run the below command to start the Django server.
python manage.py runserver
Then open the URL ‘http://127.0.0.1:8000/’ and hit enter from your keyboard, and you see the beautiful page with the logo, navigation menu, login, and register menu as shown in the below picture.
Now hover your cursor over the Register menu and click on it. Then you see the user registration form, fill in the required detail, and click on the register button.
Then after registering, it shows you the login page, enter the login details and click on the login button.
Then It will log in you and you see the profile picture at the top right side in the navigation section, so click on the profile picture, as you click on the profile picture, a drop-down menu appears.
From the drop-down menu click on the option Edit Profile to update the profile information of the logged-in user.
After clicking on the Edit Profile option, the user profile page appears, where you see the user profile information on the card and the form for updating new profile information.
So fill in the details in the form accordingly and click on the Submit button to update the user profile information.
As soon as you click on the Submit button, your user profile information is updated quickly as you see in the below picture.
You have successfully learned How to Create a User Profile Using Django.
Conclusion
In this Python tutorial, you learned how to create a user profile in Django. you learned how to design the user home page with a logo and navigation menu with a login and register menu using the Django templates and views. Additionally, you learned how to create a user profile section.
You may like to read:
- How to Create Card with Button in Django
- How to Create a Chip with Filter in Django
- How to Add Items to Cart In Django
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.