3
\$\begingroup\$

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.

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

You have a problem in the post() method.

If the user does not exist you return self.form_valid(form), so if a new user in registration form gives a validation error. You will have an error because you called form_valid() but form is not valid.

You can use return super().post(request, *args, **kwargs) instead of return self.form_valid(form). Like this:

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 super().post(request, *args, **kwargs)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I edited to improve the English spelling and grammar. But I don't know Django, so please check that my rewriting hasn't accidentally changed your meaning! \$\endgroup\$ Mar 12, 2022 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.