The purpose of this tutorial is show you how to replace the username field of django authentication system with the email field(making it unique) to authenticate and authorize the users. So without further a do let's get started.
Just type the below commands into your terminal/shell.
django-admin startproject customauth
cd customauth
python manage.py startapp accounts
Now We also need to add 'core' app to INSTALLED_APPS list inside the settings file.
INSTALLED_APPS = [
...
'accounts',
]
To create the custom user django has provided the AbstractUser class to us. So all we need to do is inherit that class and override/create our own fields.
from django.db import models
from django.contrib.auth.models import User, AbstractUser
class CustomUser(AbstractUser):
username = models.CharField(max_length=150, unique=False, blank=True, null=True)
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.email
Here we override the email field(Making it unique) and username field(Making it non-unique) and set the USERNAME_FIELD(A string describing the name of the field on the user model that is used as the unique identifier.) to 'email'.
To tell django about our custom user model. we need to set the AUTH_USER_MODEL to "Appname:UserModelName" inside the settings.py file.
AUTH_USER_MODEL = 'accounts.CustomUser'
Its time to run the migrations and start using the custom model into our project.
python manage.py makemigrations
python manage.py migrate
So in this section of tutorial, we'll be using the custom user model to set up the authentication system for our project(login, register, logout, profile functionality).So let's start with the forms.
Create a new file named 'forms.py' inside the accounts app directory and paste the below in it.
from accounts.models import CustomUser
from django.contrib.auth.forms import UserCreationForm
from django import forms
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput())
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ("email",)
we'll be using CustomUserCreationForm(which inherits from django's UserCreationForm) to register the user and LoginForm to log the user in.
Let's move on to implement the login view that will handle the logging in functionality for our project. The code is straightforward and explained by the relevant comments(wherever necessary).
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from accounts.forms import LoginForm, CustomUserCreationForm
def login_view(request):
if request.method == "POST":
form = LoginForm(request.POST)
# check if form is valid
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
# Check if credentials are valid or not.
user = authenticate(request,email = email,password = password)
if user:
# If valid then log the user in and redirect to the profile page.
login(request,user)
return redirect("accounts:profile")
else:
# Using the django messages
messages.error(request, 'Invalid Email/Password.')
else:
form = LoginForm()
return render(request,"login.html", {'form': form})
Let's move on to implement the sign up view
def signup_view(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('accounts:login')
else:
form = CustomUserCreationForm()
return render(request, 'signup.html', {'form': form})
Finally, logout and profile views.
def logout_view(request):
logout(request)
return redirect("accounts:login")
@login_required
def profile(request):
return render(request, "profile.html")
To create the frontend html templates. create a new directory/folder inside the accounts app and create three files 'login.html', 'signup.html' and 'profile.html'.
<h1>Login</h1>
{% if messages %}
{% for message in messages %}
{{ message|escape }}
{% endfor %}
{% endif %}
<form method="POSt">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
Here we have used the django messages to display the 'invalid email/password' error(If credentials are wrong).
<h1>Signup</h1>
<form method="POSt">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
<h1>Welcome {{ request.user.email }}</h1>
Now let's create the urls(mapping between URLs and views) for our application. Note: I would like to use the common django convention of keeping the each app's urls in the seperate urls.py file(Inside the app directory).
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("", include("accounts.urls"))
]
Now create a new 'urls.py' file inside the accounts app directory and paste the below code.
from django.urls import path
from accounts import views
app_name = "accounts"
urlpatterns = [
path("login/", views.login_view, name="login"),
path("signup/", views.signup_view, name="signup"),
path("logout/", views.logout_view, name="logout"),
path("profile/", views.profile, name="profile"),
]
At last, let's start the django development server(Just paste the below command in your terminal).
python manage.py runserver
Finally, its time to check if everything is working or not. just go to http://127.0.0.1:8000/signup/ and you should ready to go on your own.