I'm trying to build an email verification for user signup using CreateView
. This view check whether the user is a new or already existing inactive user? and resend verification if the user is inactive.
Here's how I did it(email sending part),
views.py
class SignUpView(CreateView):
""" SignUp view """
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'registration/register.html'
def send_activation_email(self, request, user):
""" sends email confirmation email """
uidb64 = urlsafe_base64_encode(force_bytes(user.pk))
token = token_generator.make_token(user)
domain = get_current_site(request).domain
schema = request.is_secure() and "https" or "http"
link = reverse('user_activation', kwargs={'uidb64': uidb64, 'token': token})
url = '{}://{}{}'.format(schema, domain, link)
payload = {
'receiver': user.email,
'email_body': {
'username': user.username,
'email_body': 'Verify your email to finish signing up for RapidReady',
'link': url,
'link_text': 'Verify Your Email',
'email_reason': "You're receiving this email because you signed up in {}".format(domain),
'site_name': domain
},
'email_subject': 'Verify your Email',
}
Util.send_email(payload)
messages.success(request, 'Please Confirm your email to complete registration.')
def get(self, request, *args, **kwargs):
""" Prevents authenticated user accessing registration path """
if request.user.is_authenticated:
return redirect('home')
return super(SignUpView, self).get(request, *args, **kwargs)
def form_valid(self, form):
""" Handles valid form """
form = self.form_class(self.request.POST)
user = form.save(commit=False)
user.is_active = False
user.save()
self.send_activation_email(self.request, user)
return render(self.request, 'registration/confirm_email.html', {'email': user.email})
def post(self, request, *args, **kwargs):
""" Handles existing inactive user registration attempt """
form = self.form_class(self.request.POST)
if User.objects.filter(email=request.POST['email']).exists():
user = User.objects.get(email=request.POST['email'])
if not user.is_active:
self.send_activation_email(request, user)
return render(self.request, 'registration/confirm_email.html', {'email': user.email})
# if no record found pass to form_valid
return self.form_valid(form)
util.py
class TokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return text_type(user.is_active) + text_type(user.pk) + text_type(timestamp)
token_generator = TokenGenerator()
class EmailThread(threading.Thread):
def __init__(self, email):
self.email = email
threading.Thread.__init__(self)
def run(self):
self.email.send()
class Util:
@staticmethod
def send_email(data):
msg_plain = render_to_string('email/email_normal_email.txt', data['email_body'])
msg_html = render_to_string('email/email_normal_email.html', data['email_body'])
msg = EmailMultiAlternatives(data['email_subject'], msg_plain, config('EMAIL_HOST_USER'), [data['receiver']])
msg.attach_alternative(msg_html, "text/html")
EmailThread(msg).start()
In the above code, I used form_valid()
method to handle a new user registration and the post()
method to check whether the user is new or already registered inactive user.
If no record found the post()
method will call form_valid()
method passing the form as an argument(last line in views). And this logic works just fine.
So, my main question is, 'Are there any negative effects due to this implementation?' and any advice(best practices, improvements, etc.) will be greatly appreciated.