Skip to content

Commit

Permalink
Add Contents
Browse files Browse the repository at this point in the history
  • Loading branch information
shafikshaon committed Feb 25, 2024
1 parent be85338 commit c5d17ea
Show file tree
Hide file tree
Showing 34 changed files with 3,286 additions and 0 deletions.
220 changes: 220 additions & 0 deletions content/post/001.user-registration-with-email-verification.md
@@ -0,0 +1,220 @@
---
title: "User Registration and Email Activation in Django: A Step-by-Step Guide"
description: "
Discover how to create a robust user registration system with email verification in Django, a popular Python web framework. This guide covers the necessary steps to set up email server configurations, design user-friendly registration forms, and manage account activation links. Follow along as we demonstrate best practices for creating a secure and seamless registration process, ensuring that users can only access their accounts after verifying their email addresses.
Learn how to configure Django's built-in email backends and test your email settings to make sure everything is working correctly. Explore form creation, account activation tokens, and URL patterns for managing user activation links. Walk through the process of creating and sending customized email templates, allowing users to activate their accounts and confirm their email addresses.
This comprehensive guide will help you implement a reliable and secure user registration system for your Django projects, while providing users with a seamless onboarding experience. By following these steps, you can enhance your website's security and ensure that only legitimate users gain access to your platform.
"
date: 2019-05-28T23:09:09+06:00
author: "Shafikur Rahman Shaon"
tags: [
"django",
]
series: []
draft: false
---
Assume that I have a project named **user_registration**, and it contains an app named **accounts**.

At first, we need to configure our email server. So, got to `user_registration/setting.py` and write the follwoing
lines:
```
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
MAILER_EMAIL_BACKEND = EMAIL_BACKEND
EMAIL_HOST = 'your_mail_server'
EMAIL_HOST_PASSWORD = 'your_password'
EMAIL_HOST_USER = 'your_email'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
```

To test above configuration work, open up the terminal and navigate to `user_registration` project and run following
command:

```
$ python manage.py shell
>>> from django.core.mail import send_mail
>>> send_mail( 'Subject here', 'Here is the message.', 'me@shafikshaon.com', ['shafikshaon@gmail.com'], fail_silently=False, )
```

It will return 1 as status code.
Then check your mail, a mail will arrive.

Now create a form in `accounts/templates/accounts/signup.html` and write the following code:

```
<!DOCTYPE html>
<html lang="en">
<head>
<title>Signup</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="container" style="margin-top: 50px;">
<div class="row justify-content-center">
<div class="col-md-5 shadow-sm p-3 mb-5 bg-white rounded">
<h2>Signup</h2>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="first_name">First Name:</label>
<input type="text" class="form-control" id="first_name" placeholder="Enter first name"
name="first_name">
</div>
<div class="form-group">
<label for="last_name">Last Name:</label>
<input type="text" class="form-control" id="last_name" placeholder="Enter last name"
name="last_name">
</div>
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" name="username">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
</div>
<div class="form-group">
<label for="pwd1">Password:</label>
<input type="password" class="form-control" id="pwd1" placeholder="Enter password" name="password1">
</div>
<div class="form-group">
<label for="pwd2">Confirm Password:</label>
<input type="password" class="form-control" id="pwd2" placeholder="Reenter password"
name="password2">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
```

Now create a form in `accounts/templates/accounts/acc_active_email.html` and write the following code:

```
{% autoescape off %}
Hi {{ user.username }},
Please click on the link to confirm your registration,
http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
If you think, it's not you, then just ignore this email.
{% endautoescape %}
```

Now open up `accounts/urls.py` and write the following path:

```
from django.urls import path
from accounts import views
urlpatterns = [
path('signup/', views.signup, name="signup"),
path('activate/<uidb64>/<token>/',views.activate, name='activate'),
]
```

Now open up `accounts/tokens.py` and write the following code:

```
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp) +
six.text_type(user.is_active)
)
account_activation_token = AccountActivationTokenGenerator()
```

Now open up `accounts/forms.py` and write the following code:

```
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'username')
```

Now open up `accounts/views.py` and write the following code:

```
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.sites.shortcuts import get_current_site
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 .forms import SignUpForm
from .tokens import account_activation_token
from django.contrib.auth.models import User
from django.core.mail import EmailMessage
def signup(request):
if request.method == 'GET':
return render(request, 'accounts/signup.html')
if request.method == 'POST':
form = SignUpForm(request.POST)
# print(form.errors.as_data())
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activate your account.'
message = render_to_string('accounts/acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.id)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return HttpResponse('Please confirm your email address to complete the registration')
else:
form = SignUpForm()
return render(request, 'accounts/signup.html', {'form': form})
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
else:
return HttpResponse('Activation link is invalid!')
```

When user signup, `is_active` set to `False` that means user set to inactive during signup process.
By `render_to_string()` method which data/ value send over conext. Here, data/ value send
over`accounts/acc_active_email.html` and `user`, `domain`, `uid`, and `token` data as context data.

Convert `uid` into text. Then, find user object by `uid`.
Now check `account_activation_token.check_token(user, token)` to check is this match with previously creaed token. If
match the `user.is_active` set to `True`.

0 comments on commit c5d17ea

Please sign in to comment.