Register App myapp and static file
//blogsite/settings.py import os INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', #add myapp ] # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = 'static/' MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') STATICFILES_DIRS = ( # location of your application, should not be public web accessible './static', ) LOGIN_REDIRECT_URL = '/' LOGIN_URL = '/login'Creating View
myapp/views.py
//myapp/views.py from django.shortcuts import render, redirect from django.http import HttpResponse from django.urls import reverse from django.contrib.auth import authenticate, login, logout from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.decorators import login_required import json from django.contrib.auth.models import User from django.contrib import messages from myapp.models import UserProfile from myapp.forms import UserRegistration, UpdateProfile, UpdateProfileMeta, UpdateProfileAvatar, AddAvatar context = { 'page_title' : 'Blog Site' } # Create your views here. def home(request): context['page_title'] = 'Home' return render(request, 'home.html',context) def login_user(request): logout(request) resp = {"status":'failed','msg':''} username = '' password = '' if request.POST: username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) resp['status']='success' else: resp['msg'] = "Incorrect username or password" else: resp['msg'] = "Incorrect username or password" return HttpResponse(json.dumps(resp),content_type='application/json') #Logout def logoutuser(request): logout(request) return redirect('/') def registerUser(request): user = request.user if user.is_authenticated: return redirect('home-page') context['page_title'] = "Register User" if request.method == 'POST': data = request.POST form = UserRegistration(data) if form.is_valid(): form.save() newUser = User.objects.all().last() try: profile = UserProfile.objects.get(user = newUser) except: profile = None if profile is None: UserProfile(user = newUser, dob= data['dob'], contact= data['contact'], address= data['address'], avatar = request.FILES['avatar']).save() else: UserProfile.objects.filter(id = profile.id).update(user = newUser, dob= data['dob'], contact= data['contact'], address= data['address']) avatar = AddAvatar(request.POST,request.FILES, instance = profile) if avatar.is_valid(): avatar.save() username = form.cleaned_data.get('username') pwd = form.cleaned_data.get('password1') loginUser = authenticate(username= username, password = pwd) login(request, loginUser) return redirect('home-page') else: context['reg_form'] = form return render(request,'register.html',context) @login_required def profile(request): context = { 'page_title':"My Profile" } return render(request,'profile.html',context) @login_required def update_profile(request): context['page_title'] = "Update Profile" user = User.objects.get(id= request.user.id) profile = UserProfile.objects.get(user= user) context['userData'] = user context['userProfile'] = profile if request.method == 'POST': data = request.POST form = UpdateProfile(data, instance=user) if form.is_valid(): form.save() form2 = UpdateProfileMeta(data, instance=profile) if form2.is_valid(): form2.save() messages.success(request,"Your Profile has been updated successfully") return redirect("profile") else: context['form2'] = form2 else: context['form1'] = form form = UpdateProfile(instance=request.user) return render(request,'update_profile.html',context) @login_required def update_avatar(request): context['page_title'] = "Update Avatar" user = User.objects.get(id= request.user.id) context['userData'] = user context['userProfile'] = user.profile img = user.profile.avatar.url context['img'] = img if request.method == 'POST': form = UpdateProfileAvatar(request.POST, request.FILES,instance=user) if form.is_valid(): form.save() messages.success(request,"Your Profile has been updated successfully") return redirect("profile") else: context['form'] = form form = UpdateProfileAvatar(instance=user) return render(request,'update_avatar.html',context)blogsite/urls.py
//blogsite/urls.py from django.contrib import admin from django.urls import include, path from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), ] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)myapp/urls.py
//myapp/urls.py from . import views from django.contrib import admin from django.urls import path, re_path from django.contrib.auth import views as auth_views from django.views.generic.base import RedirectView urlpatterns = [ path('redirect-admin', RedirectView.as_view(url="/admin"),name="redirect-admin"), path('', views.home, name="home-page"), path('login',auth_views.LoginView.as_view(template_name="login.html",redirect_authenticated_user = True),name='login'), path('userlogin', views.login_user, name="login-user"), path('user-register', views.registerUser, name="register-user"), path('logout',views.logoutuser,name='logout'), path('profile',views.profile,name='profile'), path('update-profile',views.update_profile,name='update-profile'), path('update-avatar',views.update_avatar,name='update-avatar'), ]Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\blogsite>python manage.py makemigrations
C:\django\blogsite>python manage.py migrate
myapp/models.py
//myapp/models.py from django.db import models from django.contrib.auth.backends import BaseBackend from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE,related_name='profile') contact = models.CharField(max_length=250) dob = models.DateField(blank=True, null = True) address = models.TextField(blank=True, null = True) avatar = models.ImageField(blank=True, null = True, upload_to= 'images/') user_type = models.IntegerField(default = 2) def __str__(self): return self.user.username def create_user_profile(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) def save_user_profile(sender, instance, **kwargs): print(instance) try: profile = UserProfile.objects.get(user = instance) except Exception as e: UserProfile.objects.create(user=instance) instance.profile.save()myapp/forms.py
//myapp/forms.py from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from myapp.models import UserProfile class UserRegistration(UserCreationForm): email = forms.EmailField(max_length=250,help_text="The email field is required.") first_name = forms.CharField(max_length=250,help_text="The First Name field is required.") last_name = forms.CharField(max_length=250,help_text="The Last Name field is required.") class Meta: model = User fields = ('email', 'username', 'password1', 'password2', 'first_name', 'last_name') def clean_email(self): email = self.cleaned_data['email'] try: user = User.objects.get(email = email) except Exception as e: return email raise forms.ValidationError(f"The {user.email} mail is already exists/taken") def clean_username(self): username = self.cleaned_data['username'] try: user = User.objects.get(username = username) except Exception as e: return username raise forms.ValidationError(f"The {user.username} mail is already exists/taken") class UpdateProfile(forms.ModelForm): username = forms.CharField(max_length=250,help_text="The Username field is required.") email = forms.EmailField(max_length=250,help_text="The Email field is required.") first_name = forms.CharField(max_length=250,help_text="The First Name field is required.") last_name = forms.CharField(max_length=250,help_text="The Last Name field is required.") current_password = forms.CharField(max_length=250) class Meta: model = User fields = ('email', 'username','first_name', 'last_name') def clean_current_password(self): if not self.instance.check_password(self.cleaned_data['current_password']): raise forms.ValidationError(f"Password is Incorrect") def clean_email(self): email = self.cleaned_data['email'] try: user = User.objects.exclude(id=self.cleaned_data['id']).get(email = email) except Exception as e: return email raise forms.ValidationError(f"The {user.email} mail is already exists/taken") def clean_username(self): username = self.cleaned_data['username'] try: user = User.objects.exclude(id=self.cleaned_data['id']).get(username = username) except Exception as e: return username raise forms.ValidationError(f"The {user.username} mail is already exists/taken") class UpdateProfileMeta(forms.ModelForm): dob = forms.DateField(help_text="The Birthday field is required.") contact = forms.CharField(max_length=250,help_text="The Contact field is required.") address = forms.CharField(help_text="The Contact field is required.") class Meta: model = UserProfile fields = ('dob', 'contact', 'address') class UpdateProfileAvatar(forms.ModelForm): avatar = forms.ImageField(help_text="The Avatar field is required.") current_password = forms.CharField(max_length=250) class Meta: model = UserProfile fields = ('avatar',) def __init__(self,*args, **kwargs): self.user = kwargs['instance'] kwargs['instance'] = self.user.profile super(UpdateProfileAvatar,self).__init__(*args, **kwargs) def clean_current_password(self): if not self.user.check_password(self.cleaned_data['current_password']): raise forms.ValidationError("Password is Incorrect") class AddAvatar(forms.ModelForm): avatar = forms.ImageField(help_text="The Avatar field is required.") class Meta: model = UserProfile fields = ('avatar',)myapp/admin.py
//myapp/admin.py import django from django.contrib import admin from myapp.models import UserProfile # Register your models here. admin.site.register(UserProfile)myapp/templates/home.html
//myapp/templates/home.html {% extends "base.html" %} {% block pageContent %} <section class="text-center"> <h4 class="mb-5"><strong>All Posts</strong></h4> <div class="row"> <h1>Homepage - Python Django Ajax Login Register User Authentication with Profile and Upload Photo </h1> </div> </section> </div> {% endblock pageContent %}myapp/templates/base.html
//myapp/templates/base.html {% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> {% if page_title %} <title>{{ page_title }} | Blog Site</title> {% else %} <title>Blog Site</title> {% endif %} <link rel="stylesheet" href="{% static 'blogApp/assets/bootstrap/css/bootstrap.min.css' %}"> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> </head> <body> {% block TopNavigation %} {% include "TopNavigation.html" %} {% endblock TopNavigation %} <main class="my-5"> <div class="container" style="padding-top: 50px;"> {% block pageContent %} {% endblock pageContent %} </div> </main> {% block ScriptBlock %} {% endblock ScriptBlock %} <footer class="bg-light text-lg-start"> <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.2);"> © {% now 'Y' %} Copyright: <a class="text-dark" href="#" target="_blank">Cairocoders</a> </div> </footer> </body> </html>myapp/templates/login.html
//myapp/templates/login.html {% extends 'base.html' %} {% load static %} {% block pageContent %} <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12"> <p><img src="{{ MEDIA_URL}}/media/images/banner1.png" class="img-fluid" /></p> <div class="card card-default rounded-0 shadow"> <div class="card-header"> <h4 class="card-title"><b>Login</b></h4> </div> <div class="card-body"> <div class="container-fluid"> <form id="login-user"> {% csrf_token %} <div class="mdc-layout-grid"> <div class="mdc-layout-grid__inner"> <div class="form-group mb-3"> <label for="username" class="control-label">Username</label> <input type="text" class="form-control rounded-0" name="username" id="username" required="required"> </div> <div class="form-group mb-3"> <label for="password" class="control-label">Password</label> <input type="password" class="form-control rounded-0" name="password" id="password" required="required"> </div> <div class="form-group mb-3"> <div class="d-flex w-100 justify-content-between align-items-center"> <div class="col-md-4"><a href="{% url 'register-user' %}">Signup</a></div> <button class="btn btn-sm rounded-0 btn-primary">Login</button> </div> </div> </div> </div> </form> </div> </div> </div> </div> </div> {% endblock pageContent %} {% block ScriptBlock %} <script> $(function() { $('#login-user').submit(function(e) { e.preventDefault(); var _this = $(this) $('.err-msg').remove(); var el = $('<div>') el.addClass("alert alert-danger err-msg") el.hide() if (_this[0].checkValidity() == false) { _this[0].reportValidity(); return false; } $.ajax({ headers: { "X-CSRFToken": '{{csrf_token}}' }, url: "{% url 'login-user' %}", data: new FormData($(this)[0]), cache: false, contentType: false, processData: false, method: 'POST', type: 'POST', dataType: 'json', error: err => { console.log(err) alert_toast("An error occured", 'error'); }, success: function(resp) { if (typeof resp == 'object' && resp.status == 'success') { el.removeClass("alert alert-danger err-msg") location.href = "{% url 'home-page' %}" } else if (resp.status == 'failed' && !!resp.msg) { el.text(resp.msg) } else { el.text("An error occured", 'error'); console.err(resp) } _this.prepend(el) el.show('slow') } }) }) }) </script> {% endblock ScriptBlock %}myapp/templates/TopNavigation.html
//myapp/templates/TopNavigation.html {% load static %} <header> <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top"> <div class="container"> <a class="navbar-brand" target="_blank" href="#">Cairocoders</a> <button class="navbar-toggler" type="button" data-mdb-toggle="collapse" data-mdb-target="#navbarExample01" aria-controls="navbarExample01" aria-expanded="false" aria-label="Toggle navigation"> <i class="fas fa-bars"></i> </button> <div class="collapse navbar-collapse" id="navbarExample01"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item active"> <a class="nav-link" aria-current="page" href="{% url 'home-page' %}">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#">All Categories</a> </li> </ul> <ul class="navbar-nav d-flex flex-row"> {% if user.id %} <li class="nav-item me-3 me-lg-0"> <a class="nav-link" href="{% url 'profile' %}"> <span class="me-1"><img src="{{ user.profile.avatar.url }}" width="30" height="30" alt="User Avatar" id="user-avatar" class="img-thumbnail rounded-circle"></span>Howdy, {{ user.first_name }} {{user.last_name}} </a> </li> <li class="nav-item me-3 me-lg-0"> <a class="nav-link" href="{% url 'logout' %}">Logout</a> </li> {% else %} <li class="nav-item me-3 me-lg-0"> <a class="nav-link" href="{% url 'login' %}">Login</a> </li> {% endif %} </ul> </div> </div> </nav> </header>myapp/templates/register.html
//myapp/templates/register.html {% extends 'base.html' %} {% load static %} {% block pageContent %} <div class="row justify-content-center"> <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12"> <div class="card card-default rounded-0 shadow"> <div class="card-header"> <h4 class="card-title"><b>Create New User</b></h4> </div> <div class="card-body"> <div class="container-fluid"> <form id="register-user" method="POST" action="{% url 'register-user' %}" enctype="multipart/form-data"> {% csrf_token %} <div class="mdc-layout-grid"> <div class="mdc-layout-grid__inner"> <div class="form-group mb-3"> <label for="first_name" class="control-label">First Name</label> <input type="text" class="form-control rounded-0" name="first_name" id="first_name" value="{{ reg_form.data.first_name }}" required="required"> </div> <div class="form-group mb-3"> <label for="last_name" class="control-label">Last Name</label> <input type="text" class="form-control rounded-0" name="last_name" id="last_name" value="{{ reg_form.data.last_name }}" required="required"> </div> <div class="form-group mb-3"> <label for="dob" class="control-label">Birthdate</label> <input type="date" class="form-control rounded-0" name="dob" id="dob" value="{{ reg_form.data.dob }}" required="required"> </div> <div class="form-group mb-3"> <label for="contact" class="control-label">Contact</label> <input type="text" class="form-control rounded-0" name="contact" id="contact" value="{{ reg_form.data.contact }}" required="required"> </div> <div class="form-group mb-3"> <label for="address" class="control-label">Address</label> <textarea rows="3" class="form-control rounded-0" name="address" id="address" required="required">{{ reg_form.data.address }}</textarea> </div> <div class="form-group mb-3"> <label for="email" class="control-label">Email</label> <input type="email" class="form-control rounded-0" name="email" id="email" value="{{ reg_form.data.email }}" required="required"> </div> <div class="form-group mb-3"> <label for="username" class="control-label">Username</label> <input type="text" class="form-control rounded-0" name="username" id="username" value="{{ reg_form.data.username }}" required="required"> </div> <div class="form-group mb-3"> <label for="password1" class="control-label">Password</label> <input type="password" class="form-control rounded-0" name="password1" id="password1" value="{{ reg_form.data.password1 }}" required="required"> </div> <div class="form-group mb-3"> <label for="password2" class="control-label">Confirm Password</label> <input type="password" class="form-control rounded-0" name="password2" id="password2" value="{{ reg_form.data.password2 }}" required="required"> </div> <div class="form-group mb-3"> <label for="avatar" class="control-label">User Avatar</label> <input type="file" class="form-control rounded-0" name="avatar" id="avatar" accept="images/*" required="required"> </div> {% for field in reg_form %} {% for error in field.errors %} <div class="alert alert-danger my-2"> <p>{{ error }}</p> </div> {% endfor %} {% endfor %} <div class="form-group mb-3"> <div class="d-flex w-100 justify-content-end"> <button class="btn btn-sm rounded-0 btn-primary col-4">Sign Up</button> </div> </div> </div> </div> </form> </div> </div> </div> </div> </div> {% endblock pageContent %}myapp/templates/profile.html
//myapp/templates/profile.html {% extends 'base.html' %} {% block pageContent%} <div class="container"> <div class="row justify-content-center"> <div class="col-lg-7 col-md-10 col-sm-12 col-xs-12"> <div class="card shadow rounded-0"> <div class="card-header"> <div class="h5 card-title fw-bold">My Profile</div> </div> <div class="card-body"> <div class="container-fluid"> <div class="row"> <div class="col-md-4"> <img src="{{ user.profile.avatar.url }}" alt="User-image" id="user-img-profile" class="img-thumbnail img-fluid"> <center><a href="{% url 'update-avatar'%}">Update Avatar</a></center> </div> <div class="col-md-8"> <dl> <dt class="text-muted">Fullname</dt> <dd class="ps-4">{{ user.first_name }} {{ user.last_name }}</dd> <dt class="text-muted">Birthday</dt> <dd class="ps-4">{{ user.profile.dob|date:"F d, Y" }}</dd> <dt class="text-muted">Contact #</dt> <dd class="ps-4">{{ user.profile.contact }}</dd> <dt class="text-muted">Address</dt> <dd class="ps-4">{{ user.profile.address }}</dd> <dt class="text-muted">Email</dt> <dd class="ps-4">{{ user.email }}</dd> <dt class="text-muted">Username</dt> <dd class="ps-4">{{ user.username }}</dd> </dl> </div> </div> </div> </div> <div class="card-footer"> <div class="d-flex w-100 text-end justify-content-end"> <a href="{% url 'update-profile' %}" class="btn btn btn-primary btn-sm bg-gradient rounded-0">Update Profile</a> </div> </div> </div> </div> </div> </div> {% endblock pageContent%}myapp/templates/update_profile.html
//myapp/templates/update_profile.html {% extends 'base.html' %} {% load static %} {% block pageContent %} <div class="row justify-content-center"> <div class="col-lg-8 col-md-10 col-sm-12 col-xs-12"> <div class="card card-default rounded-0 shadow"> <div class="card-header"> <h4 class="card-title"><b>Update Profile</b></h4> </div> <div class="card-body"> <div class="container-fluid"> <form id="register-user" method="POST" action="{% url 'update-profile' %}" enctype="multipart/form-data"> {% csrf_token %} <div class="mdc-layout-grid"> <div class="mdc-layout-grid__inner"> <div class="row"> <div class="col-md-6"> <div class="form-group mb-3"> <label for="first_name" class="control-label">First Name</label> <input type="text" class="form-control rounded-0" name="first_name" id="first_name" value="{{ userData.first_name }}" required="required"> </div> <div class="form-group mb-3"> <label for="last_name" class="control-label">Last Name</label> <input type="text" class="form-control rounded-0" name="last_name" id="last_name" value="{{ userData.last_name }}" required="required"> </div> <div class="form-group mb-3"> <label for="dob" class="control-label">Birthdate</label> <input type="date" class="form-control rounded-0" name="dob" id="dob" value="{{ userProfile.dob|date:'Y-m-d' }}" required="required"> </div> <div class="form-group mb-3"> <label for="contact" class="control-label">Contact</label> <input type="text" class="form-control rounded-0" name="contact" id="contact" value="{{ userProfile.contact }}" required="required"> </div> <div class="form-group mb-3"> <label for="address" class="control-label">Address</label> <textarea rows="3" class="form-control rounded-0" name="address" id="address" required="required">{{ userProfile.address }}</textarea> </div> </div> <div class="col-md-6"> <div class="form-group mb-3"> <label for="email" class="control-label">Email</label> <input type="email" class="form-control rounded-0" name="email" id="email" value="{{ userData.email }}" required="required"> </div> <div class="form-group mb-3"> <label for="username" class="control-label">Username</label> <input type="text" class="form-control rounded-0" name="username" id="username" value="{{ userData.username }}" required="required"> </div> <div class="form-group mb-3"> <label for="current_password" class="control-label">Current Password</label> <input type="password" class="form-control rounded-0" name="current_password" id="current_password" required="required"> </div> </div> </div> {% for field in form1 %} {% for error in field.errors %} <div class="alert alert-danger my-2"> <p>{{ error }}</p> </div> {% endfor %} {% endfor %} {% for field in form2 %} {% for error in field.errors %} <div class="alert alert-danger my-2"> <p>{{ error }}</p> </div> {% endfor %} {% endfor %} <div class="form-group mb-3"> <div class="d-flex w-100 justify-content-end"> <button class="btn btn-sm rounded-0 btn-primary col-4"> Update </button> </div> </div> </div> </div> </form> </div> </div> </div> </div> </div> {% endblock pageContent %}myapp/templates/update_avatar.html
//myapp/templates/update_avatar.html {% extends 'base.html' %} {% load static %} {% block pageContent %} <div class="row justify-content-center"> <div class="col-lg-8 col-md-10 col-sm-12 col-xs-12"> <div class="card card-default rounded-0 shadow"> <div class="card-header"> <h4 class="card-title"><b>Update Profile</b></h4> </div> <div class="card-body"> <div class="container-fluid"> <form id="register-user" method="POST" action="{% url 'update-avatar' %}" enctype="multipart/form-data"> {% csrf_token %} <div class="mdc-layout-grid"> <div class="mdc-layout-grid__inner"> <div class="row"> <div class="col-md-6"> <img src="{{ img }}" alt="User-image" id="user-img-profile" class="img-thumbnail img-fluid"> </div> <div class="col-md-6"> <div class="form-group mb-3"> <label for="avatar" class="control-label">Avatar</label> <input type="file" class="form-control rounded-0" name="avatar" id="avatar" accept="image/*" onchange="DisplayImage(this)" required="required"> </div> <div class="form-group mb-3"> <label for="current_password" class="control-label">Current Password</label> <input type="password" class="form-control rounded-0" name="current_password" id="current_password" required="required"> </div> </div> </div> {% for field in form %} {% for error in field.errors %} <div class="alert alert-danger my-2"> <p>{{ error }}</p> </div> {% endfor %} {% endfor %} <div class="form-group mb-3"> <div class="d-flex w-100 justify-content-end"> <button class="btn btn-sm rounded-0 btn-primary col-4"> Update </button> </div> </div> </div> </div> </form> </div> </div> </div> </div> </div> {% endblock pageContent %} {% block ScriptBlock %} <script> function DisplayImage(input) { console.log(input.files) if (event.target.files[0]) { var reader = new FileReader(); reader.onload = function() { var output = $('#user-img-profile'); output.attr('src', reader.result) }; reader.readAsDataURL(input.files[0]); } }; </script> {% endblock ScriptBlock %}Run : C:\django\blogsite>python manage.py runserver