Session Overview

  • Edit User Profile
  • Upload Profile Photo
  • Display Profile Photo
  • Protect Pages using @login_required
  • Comment Module
  • Display Comments

Edit User Profile

During Registration, only basic User information is stored. Now we will allow users to update their Profile Photo, Mobile Number and Bio.

Step 1 - Create UserProfileForm
from django import forms

from .models import UserProfile


class UserProfileForm(forms.ModelForm):

    class Meta:

        model = UserProfile

        fields = [

            "ProfilePhoto",

            "Mobile",

            "Bio"

        ]
Step 2 - Update views.py
from django.contrib.auth.decorators import login_required

from .forms import UserProfileForm


@login_required

def profile(request):

    profile = request.user.userprofile

    if request.method == "POST":

        form = UserProfileForm(

            request.POST,

            request.FILES,

            instance=profile

        )

        if form.is_valid():

            form.save()

    else:

        form = UserProfileForm(

            instance=profile

        )

    return render(

        request,

        "profile.html",

        {

            "form": form

        }

    )
Result The logged-in user can edit only their own Profile information.
Understanding instance=profile

The instance parameter tells Django to update an existing record instead of creating a new one.

UserProfileForm(

    instance=profile

)

Without the instance parameter, Django would create a new record instead of updating the existing UserProfile.

Upload Profile Photo

Since the Profile contains an ImageField, we must allow users to upload image files.

Step 1 - Create profile.html
{% extends 'base.html' %}

{% block content %}

<div class="container mt-5">

    <div class="row justify-content-center">

        <div class="col-md-6">

            <div class="card shadow">

                <div class="card-header">

                    <h3>My Profile</h3>

                </div>

                <div class="card-body">

                    <form method="POST"
                          enctype="multipart/form-data">

                        {% csrf_token %}

                        {{ form.as_p }}

                        <button class="btn btn-primary">

                            Save Profile

                        </button>

                    </form>

                </div>

            </div>

        </div>

    </div>

</div>

{% endblock %}
Step 2 - Update blog/urls.py
path(

    "profile/",

    views.profile,

    name="profile"

),
Result Users can upload a Profile Photo along with their Mobile Number and Bio.
Important Concepts Used
Concept Purpose
request.FILES Receives uploaded image files.
multipart/form-data Required for uploading files using HTML forms.
ModelForm Creates a form directly from a Django Model.
ImageField Stores uploaded Profile Photos.

Display Profile Photo in Navigation Bar

After uploading a Profile Photo, we can display it in the Navigation Bar along with the logged-in Username.

If the user has not uploaded a Profile Photo, a default User icon will be displayed.

Update base.html
{% if user.is_authenticated %}

<li class="nav-item dropdown">

    <a class="nav-link dropdown-toggle"
       href="#"
       role="button"
       data-bs-toggle="dropdown">

        {% if user.userprofile.ProfilePhoto %}

        <img src="{{ user.userprofile.ProfilePhoto.url }}"
             width="35"
             height="35"
             class="rounded-circle me-2">

        {% else %}

        <i class="fa-solid fa-user"></i>

        {% endif %}

        {{ user.username }}

    </a>

    <ul class="dropdown-menu">

        <li>

            <a class="dropdown-item"
               href="{% url 'profile' %}">

                My Profile

            </a>

        </li>

        <li>

            <a class="dropdown-item"
               href="{% url 'logout' %}">

                Logout

            </a>

        </li>

    </ul>

</li>

{% endif %}
Result The Navigation Bar now displays the user's Profile Photo if available; otherwise, it shows a default User icon.
Understanding the Template Code
Code Purpose
user.userprofile Accesses the UserProfile linked to the logged-in User.
ProfilePhoto.url Returns the URL of the uploaded Profile Photo.
{% if %} Checks whether the Profile Photo exists.
rounded-circle Displays the image as a circular profile picture.

Protect Pages using @login_required

Some pages should only be accessible to authenticated users.

Django provides the @login_required decorator to restrict access to specific Views.

Update views.py
from django.contrib.auth.decorators import login_required


@login_required

def profile(request):

    profile = request.user.userprofile

    ...

    return render(
        request,
        "profile.html",
        {
            "form": form
        }
    )
Configure Login URL

Open settings.py and add:

LOGIN_URL = "login"
Result If a user tries to access the Profile page without logging in, Django automatically redirects them to the Login page.
Understanding @login_required

The @login_required decorator checks whether the current user is authenticated before executing the View.

User Requests Profile Page

        │

        ▼

Is User Logged In?

   │             │

  Yes            No

   │             │

   ▼             ▼

Open Page    Redirect to Login

This helps protect sensitive pages from unauthorized access.

Comment Module

A Comment allows registered users to share their thoughts about a Blog Post.

Each Comment belongs to one Blog Post and is submitted by one User.

Step 1 - Update models.py
from django.contrib.auth.models import User


class Comment(models.Model):

    Post = models.ForeignKey(

        Post,

        on_delete=models.CASCADE

    )

    User = models.ForeignKey(

        User,

        on_delete=models.CASCADE

    )

    Comment = models.TextField()

    CreatedOn = models.DateTimeField(

        auto_now_add=True

    )

    class Meta:

        db_table = "Comments"

    def __str__(self):

        return self.User.username
Step 2 - Create Migration
python manage.py makemigrations

python manage.py migrate
Step 3 - Create CommentForm
from django import forms

from .models import Comment


class CommentForm(forms.ModelForm):

    class Meta:

        model = Comment

        fields = [

            "Comment"

        ]
Result The project is now ready to allow users to submit Comments for Blog Posts.

Display Comments

Logged-in users can submit Comments from the Blog Details page.

Step 1 - Update views.py
from .forms import CommentForm


@login_required

def blogDetails(request, slug):

    post = get_object_or_404(

        Post,

        Slug=slug,

        IsPublished=True

    )

    comments = Comment.objects.filter(

        Post=post

    ).order_by("-CreatedOn")

    if request.method == "POST":

        form = CommentForm(request.POST)

        if form.is_valid():

            comment = form.save(commit=False)

            comment.Post = post

            comment.User = request.user

            comment.save()

            return redirect(

                "blogdetails",

                slug=post.Slug

            )

    else:

        form = CommentForm()

    return render(

        request,

        "blogdetails.html",

        {

            "post": post,

            "form": form,

            "comments": comments

        }

    )
Step 2 - Update blogdetails.html
<hr>

<h3>Comments</h3>

<form method="POST">

    {% csrf_token %}

    {{ form.as_p }}

    <button class="btn btn-primary">

        Post Comment

    </button>

</form>

<hr>

{% for comment in comments %}

<div class="card mb-3">

    <div class="card-body">

        <strong>

            {{ comment.User.username }}

        </strong>

        <small class="text-muted">

            {{ comment.CreatedOn }}

        </small>

        <p class="mt-2 mb-0">

            {{ comment.Comment }}

        </p>

    </div>

</div>

{% empty %}

<p>

    No comments yet.

</p>

{% endfor %}
Result Registered users can submit Comments and view all existing Comments for a Blog Post.
New Concepts Used
Concept Purpose
commit=False Creates the Comment object without saving it immediately.
comment.Post = post Associates the Comment with the current Blog Post.
comment.User = request.user Stores the logged-in User as the author of the Comment.
redirect() Refreshes the page after saving the Comment.

Quick Revision

User Profile
  • ModelForm
  • instance
  • Update Record
Image Upload
  • request.FILES
  • ImageField
  • multipart/form-data
Navigation
  • Profile Photo
  • Conditional Rendering
  • User Dropdown
Authentication
  • @login_required
  • Protected Views
  • LOGIN_URL
Comment Model
  • ForeignKey
  • ModelForm
  • CreatedOn
Comment Submission
  • commit=False
  • request.user
  • redirect()
Concepts Learned Today
✓ Edit User Profile

✓ Upload Profile Photo

✓ Display Profile Photo in Navbar

✓ @login_required

✓ Comment Model

✓ Display Comments

✓ commit=False

✓ request.user

Assignment

Continue Developing the News Portal

Implement today's User Profile and Comment features in your News Portal.

  1. Create a User Profile page where users can update:
    • Profile Photo
    • Mobile Number
    • Bio
  2. Display the uploaded Profile Photo in the Navigation Bar. If no photo is available, display the default User icon.
  3. Protect the Profile page using @login_required.
  4. Create a News Comment model with the following fields:
    • NewsPost
    • User
    • Comment
    • CreatedOn
  5. Create a CommentForm using ModelForm.
  6. Allow only logged-in users to view news details page.
  7. Display all Comments below the News Details page with:
    • User Name
    • Comment
    • Date & Time