DEV Community

Cover image for Django Registration,Login Logout and Profile Easy Setup
Suman
Suman

Posted on

Django Registration,Login Logout and Profile Easy Setup

Registration Setup

Create a new app User
-- to seperate the logic of registeration,login and logout and create a module that can be integrated in any Django application

In main app urls.py :

urlpatterns = [
    path('users/', include('users.urls'))
]
Enter fullscreen mode Exit fullscreen mode

in User urls.py :

from django.urls import path
from .import views

urlpatterns = [
    path('sign_up/', views.index, name='users-sign-up')
]
Enter fullscreen mode Exit fullscreen mode

Create forms.py in User app and write the following:

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User

class SignUpForm(UserCreationForm):
    email = forms.EmailField(required=True)
    class Meta:
        model = User
        fields = ['username','email','password1','password2'] 

        def __init__(self, *args, **kwargs):
            super(SignUpForm, self).__init__(*args, **kwargs)

            for fieldname in ['password1','password2']:
                self.fields[fieldname].help_text = None
Enter fullscreen mode Exit fullscreen mode

In views (User) :

from django.shortcuts import render,redirect
from .forms import SignUpForm

def index(request):
    if request.method == "POST":
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('login')
    else:
        form = SignUpForm()
    context = {
        'form':form
    }
    return render(request,'User/sign_up.html',context) 
Enter fullscreen mode Exit fullscreen mode

In Sign_up.html :

<title>{% block title %}Sign Up{% endblock %}</title>
<form method="POST">
    {% csrf_token %}
    {{ form|crispy }}
    <input type="submit" value="Register" class="btn btn-primary">
</form>
Enter fullscreen mode Exit fullscreen mode

Add this to base.html to show title dynamically:

<title>{% block title %}{% endblock %}</title>
Enter fullscreen mode Exit fullscreen mode

Login Setup

In the same urls.py:

from django.contrib.auth import views as auth_view

path('login/', auth_view.LoginView.as_view(template_name='User/login.html'), name='login'),
Enter fullscreen mode Exit fullscreen mode

In Sign_in.html :

<title>{% block title %}Sign In{% endblock %}</title>
<form method="POST">
    {% csrf_token %}
    {{ form|crispy }}
    <input type="submit" value="Login" class="btn btn-primary">
</form>
Enter fullscreen mode Exit fullscreen mode

In settings.py

LOGIN_REDIRECT_URL = 'home' 
Enter fullscreen mode Exit fullscreen mode

Optimize your navbar :

<div class="collapse navbar-collapse" id="navbarNav">
  <ul class="navbar-nav ms-auto">
    {% if request.user.is_authenticated %}
      <li class="nav-item">
        <a class="nav-link" href="{% url 'blog:create' %}">New BlogPost</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'logout' %}">Logout</a>
      </li>
    {% else %}
      <li class="nav-item">
        <a class="nav-link" href="{% url 'login' %}">Login</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'register' %}">Register</a>
      </li>
    {% endif %}
  </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Logout Setup

In the same urls.py:

path('logout/', views.LogoutView.as_view(next_page='home'), name='logout'),
Enter fullscreen mode Exit fullscreen mode

In Logout.html : (only for the flow of execution)

<title>{% block title %}Logout{% endblock %}</title>
<form method="POST">
    {% csrf_token %}
    {{ form|crispy }}
    <input type="submit" value="Login" class="btn btn-primary">
</form>
<hr>
<div class="alert alert-info">
  You have been logged out.
</div> 
Enter fullscreen mode Exit fullscreen mode

Use this url template tag wherever required in navbar:

{% url 'logout' %}
Enter fullscreen mode Exit fullscreen mode

Profile Setup

In forms.py

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from .models import Profile

class SignUpForm(UserCreationForm):
    email = forms.EmailField(required=True)
    class Meta:
        model = User
        fields = ['username','email','password1','password2']

class EditProfile(forms.ModelForm):
    class Meta:
        model = User
        fields = ['username','email']

    def __init__(self, *args, **kwargs):
        super(EditProfile, self).__init__(*args, **kwargs)

        for fieldname in ['username', 'email']:
                self.fields[fieldname].help_text = None

class EditPro(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['bio','pic']

        widgets = {
                'bio': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'placeholder': 'Write about yourself...'}),
                'pic': forms.ClearableFileInput(attrs={'class': 'form-control'}),
            }

    def __init__(self, *args, **kwargs):
        super(EditPro, self).__init__(*args, **kwargs)

        for fieldname in ['bio', 'pic']:
                self.fields[fieldname].help_text = None
Enter fullscreen mode Exit fullscreen mode

In views.py

from django.shortcuts import render,redirect
from .forms import SignUpForm,EditProfile,EditPro
from django.contrib import messages
from django.contrib.auth.views import LogoutView
from myBlog.models import UserPost,Category
from django.contrib.auth.decorators import login_required
# Create your views here.

def index(request):
    if request.method == "POST":
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('new_login')
    else:
        form = SignUpForm()
    context = {
        'form':form
    }
    return render(request,'User/sign_up.html',context)

@login_required
def userProfile(request):
    if request.method == "POST":
        u_form = EditProfile(request.POST or None,instance=request.user)
        p_form = EditPro(request.POST or None,request.FILES or None,instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            return redirect('profile')
    else:
        u_form = EditProfile(instance=request.user)
        p_form = EditPro(instance=request.user.profile)

    blog_count = UserPost.objects.filter(author=request.user).count()
    category = Category.objects.filter(status = 0)
    context = {
        'u_form':u_form,
        'p_form':p_form,
        'blog_count':blog_count,
        'category':category

    }
    return render(request,'User/profile.html',context)
Enter fullscreen mode Exit fullscreen mode

*In urls.py *

path('profile/',views.profile, name='user-profile'),
Enter fullscreen mode Exit fullscreen mode

In navbar.html

<a href="{% url 'user-profile' %}">Profile</a>
Enter fullscreen mode Exit fullscreen mode

In User/profile.html

{% extends "base.html" %}
{% load crispy_forms_tags %}

{% block title %}Profile Page{% endblock %}

{% block content %}
<div class="container">
    <div class="row mt-5 pt-3">
        <div class="col-md-6 offset-md-3">
            <div class="card my-3 shadow">
                <div class="card-body">
                    <div class="row">
                        <!-- Profile Image -->
                        <div class="col-md-4 text-center">
                            {% if user.profile.pic %}
                                <img src="{{ user.profile.pic.url }}" 
                                     class="img-fluid rounded-circle mb-3 shadow-sm" 
                                     alt="{{ user.username }}">
                            {% else %}
                                <img src="https://via.placeholder.com/150" 
                                     class="img-fluid rounded-circle mb-3 shadow-sm" 
                                     alt="Default Profile">
                            {% endif %}
                            <h5 class="mt-2">{{ user.username }}</h5>
                        </div>

                        <!-- Profile Form -->
                        <div class="col-md-8">
                            <form method="POST" enctype="multipart/form-data">
                                {% csrf_token %}
                                {{ form|crispy }}
                                <div class="d-grid">
                                    <button type="submit" class="btn btn-primary">
                                        Update Profile
                                    </button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

Bootstrap Modal Example (optional)

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Edit Profile
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <div class="modal-header">
          <h1 class="modal-title fs-5" id="exampleModalLabel">Edit Profile</h1>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>

        <div class="modal-body">
          <div class="row">
            <div class="col-md-4 text-center">
              <img src="{{ user.profile.pic.url }}" alt="Profile Picture" class="img-fluid rounded">
            </div>
            <div class="col-md-8">
              {{ u_form|crispy }}
              {{ p_form|crispy }}
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="submit" class="btn btn-primary">Save changes</button>
        </div>
      </form>
    </div>
  </div>
</div>

Enter fullscreen mode Exit fullscreen mode

In User/models.py

from django.db import models
from django.contrib.auth.models import User
import os,datetime
from django.core.validators import FileExtensionValidator

class Profile(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    pic = models.ImageField(default='default.png',upload_to='avatars/',validators=[FileExtensionValidator(['png','jpg','jpeg','webp'])])
    bio = models.TextField(blank=True,null=True)

    def __str__(self):
        return self.user.username
Enter fullscreen mode Exit fullscreen mode

Serve Media Files

pip install pillow
Enter fullscreen mode Exit fullscreen mode
# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Enter fullscreen mode Exit fullscreen mode
# urls.py
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)
Enter fullscreen mode Exit fullscreen mode

Dump your all Static files for production

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / "staticfiles"
Enter fullscreen mode Exit fullscreen mode
python manage.py collectstatic
Enter fullscreen mode Exit fullscreen mode

admins.py

from django.contrib import admin
from .models import Profile

admin.site.register(Profile)

Enter fullscreen mode Exit fullscreen mode

In template

<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Upload</button>
</form>
Enter fullscreen mode Exit fullscreen mode

Also Add default.jpg/png in media folder to show default pic
Use Django Signals to create profile automatically after user sign up

from .models import Profile
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

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

@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()
Enter fullscreen mode Exit fullscreen mode

apps.py

from django.apps import AppConfig

class UserConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'user'

    def ready(self):
        import user.signals
Enter fullscreen mode Exit fullscreen mode

That's it :) Happy Coding you all.

Top comments (0)