Part 2 : Django HTML Integration, Django Email Confirmation

Hello Techies,

In this blog, we will check how to use Django email confirmation, and Django HTML integration.

In my previous blog, I have covered the basics of  Django login and registration features which is Part 1. So you can check that blog also.

Below are the points you are going to learn

  1. Django HTML Integration
  2. Django email confirmation

1. Django HTML Integration

Let’s look at an example of Django HTML integration. So you get an idea of ​​how to integrate Django HTML and add static files to it.

For styling, we need CSS files where we need separate static folders and in this folder, we need sub-folders like CSS, and images that can handle their files independently.

So let’s create a static folder and sub-folders in the account app. I hope you are referring to my previous blog Django login and registration application to check how to do Django HTML Integration and how to add static files in it.

Django HTML Integration (Static folder structure)

Add style.css in accounts/static/css 

/*--reset--*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
dl,
dt,
dd,
ol,
nav ul,
nav li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
    display: block;
}

ol,
ul {
    list-style: none;
    margin: 0px;
    padding: 0px;
}

blockquote,
q {
    quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
    content: '';
    content: none;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

.clearfix {
    clear: both;
}

/*--start editing from here--*/

a {
    text-decoration: none;
}

.txt-rt {
    text-align: right;
}

/* text align right */

.txt-lt {
    text-align: left;
}

/* text align left */

.txt-center {
    text-align: center;
}

/* text align center */

.float-rt {
    float: right;
}

/* float right */

.float-lt {
    float: left;
}

/* float left */

.pos-relative {
    position: relative;
}

/* Position Relative */

.pos-absolute {
    position: absolute;
}

/* Position Absolute */

.vertical-base {
    vertical-align: baseline;
}

/* vertical align baseline */

.vertical-top {
    vertical-align: top;
}

/* vertical align top */

nav.vertical ul li {
    display: block;
}

/* vertical menu */

nav.horizontal ul li {
    display: inline-block;
}

/* horizontal menu */

img {
    max-width: 100%;
}

/*--end reset--*/

body {
	font-family: 'Poppins', sans-serif;
    font-size: 100%;
    background: url(../images/1.jpg)no-repeat center top;
    background-size: cover;
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    -ms-background-size: cover;
    background-attachment: fixed;
    text-align: center;
}

.body_container {
    display: -webkit-flex;
    display: -webkit-box;
    display: -moz-flex;
    display: -moz-box;
    display: -ms-flexbox;
    display: flex;
    justify-content: center;
    align-items: center;
    -webkit-box-pack: center;
    -moz-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
}

h1 {
    font-size: 3.2em;
    text-transform: capitalize;
    color: #fff;
    text-shadow: 1px 1px 1px #000;
    letter-spacing: 3px;
    margin: .8em 1vw;
    text-align: center;
}

.body_container form {
    max-width: 500px;
    margin: 0 5vw;
    border-radius: 8px;
    background: transparent;
    padding: 3.5vw;
    border: solid #fff;
    border-width: 5px;
    box-sizing: border-box;
    display: flex;
    display: -webkit-flex;
    flex-wrap: wrap;
}

.body_container label {
    font-size: 14px;
    color: #fff;
    float: left;
    text-align: left;
    margin-bottom: 5px;
    text-transform: capitalize;
    letter-spacing: 2px;
    cursor: pointer;
}

.agile-field-txt {
    flex-basis: 100%;
    -webkit-flex-basis: 100%;
    margin-bottom: 1.5em;
}

.body_container label i {
    font-size: 1.1em;
    margin-right: 3px;
    color: #fd5c63;
}

.body_container input[type="text"],
.body_container input[type="password"] {
    width: 100%;
    color: #333;
    outline: none;
    font-size: 15px;
    letter-spacing: 1px;
     border-radius: 8px;
    padding: 15px;
    box-sizing: border-box;
    border: none;
    box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.49);
    -webkit-appearance: none;
    background: #fff;
	font-family: 'Poppins', sans-serif;
}

.check1 {
    text-align: left;
}

label.check {
    float: none;
}

.agile_label {
    text-align: left;
    margin: 10px 0 0;
}

.body_container.w3l-sub {
    margin-top: 1em;
    flex-basis: 100%;
    -webkit-flex-basis: 100%;
}

.body_container input[type=submit] {
    width: 100%;
    padding: 0.5em 0;
    font-size: 1.1em;
    letter-spacing: 2px;
    cursor: pointer;
    border: none;
    border-radius: 8px;
    border: 2px solid #fd5c63;
    background: #fd5c63;
    color: #fff;
	margin-top:1em;
    outline: none;
    transition: 0.5s all ease;
    -webkit-transition: 0.5s all ease;
    -moz-transition: 0.5s all ease;
    -o-transition: 0.5s all ease;
    -ms-transition: 0.5s all ease;
	font-family: 'Poppins', sans-serif;
}

.body_container input[type=submit]:hover {
    background: transparent;
	border: 2px solid #fff;
    color: #fff;
}

.w3ls-bot {
    width: 100%;
}

/* switch */

label.switch {
    position: relative;
    display: inline-block;
    height: 23px;
    padding-left: 5em;
    cursor: pointer;
    color: #fff;
}

li:nth-child(2) a,
label.switch {
    text-transform: capitalize;
    font-size: 14px;
    letter-spacing: 2px;
}

.switch input {
    display: none;
}

.slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 22%;
    background-color: #999;
    -webkit-transition: .4s;
    transition: .4s;
}

.slider:before {
    position: absolute;
    content: "";
    height: 15px;
    width: 15px;
    left: 4px;
    bottom: 4px;
    background-color: white;
    -webkit-transition: .4s;
    transition: .4s;
}

input:checked+.slider {
    background-color: #fd5c63;
}

input:focus+.slider {
    box-shadow: 0 0 1px #2196F3;
}

input:checked+.slider:before {
    -webkit-transform: translateX(26px);
    -ms-transform: translateX(26px);
    transform: translateX(26px);
}

/* Rounded sliders */

.slider.round {
    border-radius: 34px;
}

.slider.round:before {
    border-radius: 50%;
}

/* //switch */

.switch-agileits {
    width: 100%;
    float: left;
}

.form-end {
}
.errorlist{
    color:red;
}

/*--responsive--*/

@media(max-width:1920px) {
    h1 {
        font-size: 3.5vw;
    }
}

@media(max-width:1024px) {
    h1 {
        font-size: 4.5vw;
    }
}

@media(max-width:800px) {
    h1 {
        font-size: 5vw;
    }
}

@media(max-width:480px) {
    h1 {
        font-size: 2.5em;
    }
    .body_container form {
        padding: 7.5vw;
    }
	.body_container input[type="text"], .body_container input[type="password"] {
		padding: 13px 15px;
	}
	.body_container input[type=submit] {
		padding: 0.4em 0;
		font-size: 1em;
	}
}

@media(max-width:440px) {
    h1 {
        font-size: 2.3em;
    }
    .parent {
        display: block;
    }

}

@media(max-width:320px) {
    h1 {
        font-size: 1.8em;
    }
    .body_container form {
        padding: 25px 8px;
    }
}

/*--//responsive--*/

Use the below image in images folder.

Create the base.html file in accounts/templates/base.html and add the below code in it. These templates help when you want to use the same code or layout in more than one place.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>{% block title %}Django Simple Login{% endblock %}</title>
  {% load static %}
  <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}"/>
</head>
<body>
  <header>
    <h1>Django Registration and Login</h1>
    {% if user.is_authenticated %}
      Welcome {{ user.username }}!
      <a href="{% url 'logout' %}">logout</a>
    {% else %}
      <a href="{% url 'login' %}" style="font-size: 25px;font-weight: 600;color:#bca0ff">login</a>&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="{% url 'sign_up' %}" style="font-size: 25px;font-weight: 600;color:#bca0ff">Create New Account</a>
    {% endif %}
  </header>
  <hr>
  <main>
    {% block content %}
    {% endblock %}
  </main>
  <hr>
  <footer>
    <a href="http://techpluslifestyle.com">techpluslifestyle.com</a>
  </footer>
</body>
</html>

As you can see in the above code where multiple tags we used like {% block title %} tag will replace with html title tag , {% load static %}, this tag tells the template engine to use the files in the static folder in this template and using the {% static ‘static_filename’ %} we can add the multiple static files in our template, {% block content %} tag use for page content.

Create the home.html file in accounts/templates/home.html and add the below code in it.

{% extends 'base.html' %}

{% block title %}Login{% endblock %}

{% block content %}
  <div style="font-size: 15px;font-weight: 300;color:white">
      <p>Welcome to Tech Plus Lifestyle blogs. </p>
  </div>
{% endblock %}
Django HTML Integration(Index page)
Django HTML Integration(login page)

Html code for Login.html

{% extends 'base.html' %}
{% block content %}
  <div class="body_container box box--big">
		<!-- form starts here -->
		<form id="login-form" method="post" action="#">
            {% csrf_token %}
			<div class="agile-field-txt">
				<label>
					<i class="fa fa-user" aria-hidden="true"></i> username </label>
				<input id="id_username" name="username" placeholder="Enter your name " required=""
                                   type="text" class="form-control">
			</div>
			<div class="agile-field-txt">
				<label>
					<i class="fa fa-envelope" aria-hidden="true"></i> password </label>
					<input name="password" type="password" class="form-control"
					   placeholder="Enter your password " required="" id="myInput id_password" >
			</div>
			{% if form.errors %}
				<p class=" label label-danger" style="color:red">
					Your username and password didn't match.
					Please try again.
				</p>
			{% endif %}
			<div class="w3ls-bot">
				<div class="form-end">
					<input type="submit" value="LOGIN">
				</div>
				<div class="clearfix"></div>
                <br/>
                <div class="form-end">
                    <a href="{% url 'sign_up' %}" style="background-color: #555555;padding: 15px 32px;display: inline-block;
                    color:white;margin: 4px 2px;">Create New Account</a>
                </div>
			</div>
		</form>
	</div>

{% endblock %}
Django HTML Integration(login page)
Django HTML Integration(login page)

2. Django Email Confirmation

Let’s see how to create sign-up functionality with email confirmation. Using this functionality the user will not be able to access the login account without email confirmation.

Add url in account/urls.py file

from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
from django.contrib.auth.forms import UserCreationForm

from . import views

urlpatterns = [
    path('sign_up/', views.sign_up, name="sign_up"),
    path('activate/<uidb64>/<token>', views.activate, name='activate'),
    path('login', auth_views.LoginView.as_view(),{'template_name': 'registration/login.html'}, name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]

Add below code into accounts/models.py file

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)
    email_confirmed = models.BooleanField(default=False)
    # other fields...

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

Add the below code in setting.py file for email configuration.

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

DEFAULT_FROM_EMAIL = '[email protected]' # here provide your gmail email id
SERVER_EMAIL = '[email protected]' # here provide your gmail email id
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com' # here provide your gmail email id
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'example' # gmail password
EMAIL_PORT = 587

Now add the sign_up function in account/views.py file

from django.contrib.auth import login
from django.contrib.sites.shortcuts import get_current_site
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.template.loader import render_to_string
from django.core.mail import EmailMessage
from django.http import HttpResponse

from .token import account_activation_token
from .forms import SignUpForm


def sign_up(request):
    if request.method == 'POST':

        form = SignUpForm(request.POST)
        if form.is_valid():
            user_obj = form.save(commit=False)
            user_obj.is_active = False
            user_obj.save()
            current_site = get_current_site(request)
            subject = 'Activate Your Account'
            message = render_to_string('account_activation_email.html', {
                'user': user_obj,
                'domain': current_site.domain,
                'uid': urlsafe_base64_encode(force_bytes(user_obj.pk)),
                'token': account_activation_token.make_token(user_obj),
            })
            to_email = form.cleaned_data.get('email')
            email = EmailMessage(subject, message, to=[to_email], from_email='[email protected]')
            email.send()
            return HttpResponse('We have sent you an email, please confirm your email address to complete registration')
    else:
        form = SignUpForm()
    return render(request, 'sign_up.html', {'form': form})

Create the forms.py file in accounts folder and add the below code in accounts/forms.py file.

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


class SignUpForm(UserCreationForm):
    email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')

    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2', )

HTML Code For Sign Up Page

{% extends 'base.html' %}

{% block content %}
<div class="body_container box box--big">
		<!-- form starts here -->

		<form id="sign-up-form" method="post" action="#">
            {% csrf_token %}
			<div class="agile-field-txt">
				<label> Username </label>
				<input id="id_username" name="username" placeholder="Enter your name " required=""
                                   type="text" class="form-control">
			</div>
			<div class="agile-field-txt">
				<label> Email </label>
				<input id="id_email" name="email" placeholder="Enter your email " required=""
                                   type="text" class="form-control">
			</div>
			<div class="agile-field-txt">
				<label> password </label>
				<input name="password1" type="password" class="form-control"
					   placeholder="Enter your password " required="" id="id_password" >
			</div>
            <div class="agile-field-txt">
				<label>confirm password </label>
				<input name="password2" type="password" class="form-control"
					   placeholder="Enter your confirm password" required="" id="id_password" >
			</div>
                {% if form.errors %}
                    {% for field in form %}
                        {% for error in field.errors %}
                            <p style="color: white">{{ error }}</p>
                        {% endfor %}
                    {% endfor %}
                {% endif %}
			<div class="w3ls-bot">
				<div class="form-end">
					<input type="submit" value="Create">
				</div>
				<div class="clearfix"></div>
				<br/>
				<div class="form-end">
                    <a style="background-color: #555555;padding: 15px 32px;display: inline-block;
                    color:white;margin: 4px 2px;" href="{% url 'login' %}">Login</a>
                </div>
			</div>
		</form>
	</div>
{% endblock %}
Django HTML Integration(sign-up page)
Django HTML Integration(sign-up page)

Let’s write the code for token for this function we will create one separate file in accounts folder. So create token.py file in accounts folder and add below code.

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from six import text_type

class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            text_type(user.pk) + text_type(timestamp) +
            text_type(user.profile.email_confirmed)
        )

account_activation_token = AccountActivationTokenGenerator()

Email sign-up functionality is now complete. We will now develop a feature for email activation clicks. So now first add URL in account/urls.py file.

path('activate/<uidb64>/<token>', views.activate, name='activate'),

Add below code for activate function in accounts/views.py file.

from django.contrib.auth import login
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from .token import account_activation_token

def activate(request, uidb64, token):
    try:
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except Exception as e:
        user = None

    if user is not None and account_activation_token.check_token(user, token):
        user.is_active = True
        user.profile.email_confirmed = True
        user.save()
        login(request, user)
        return redirect('home')
    else:
        return render(request, 'account_activation_invalid.html')</code></pre></amp-fit-text>

Create the Template for the Account activation in the accounts/template folder and add the below code in it.

{% autoescape off %}
Hi {{ user.username }},

Please click on the link below to confirm your registration:

http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
{% endautoescape %}
Django HTML Integration(Activation link)

Let’s check Django-registration send activation email which I received.

django-registration send activation email
Django HTML Integration (Django email confirmation)

So this is one example of send email validation in Django.

If you’re experiencing email issues, such as unable to receive any mail after you sign up, use Google’s less secure app option and enable that option. Check the below image for the same.

allow less secure app
Django HTML Integration (Less secure app access)

I hope you understand every step of How to create a Django HTML Integration and Django email confirmation. If you still have any query do comment below.

Refer a below GitHub link for source code(Django HTML Integration and Django email confirmation).

https://github.com/pranalikambli/login_registration_with_django_extra_features

thank you

Leave a Comment