1

I came across a problem while developing my Django application. I need to register users and send a link to activate the user account, but when I click the link it does not activate the account, it just returns to my home page. How can I activate the user account?

My code for urls.py:

from django.contrib import admin
from django.urls import path
from contas.views import home, nova_transacao, update, delete, notSuper, signUp, activation_sent, activate

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home, name='url_home'),
    path('update/<int:pk>/', update, name='url_update'),
    path('delete/<int:pk>/', delete, name='url_delete'),
    path('403/', notSuper, name='url_notSuper'),
    path('form/', nova_transacao, name='url_novaTransacao'),
    path('signup/', signUp, name='url_signUp'),
    path('signup/activation_sent/', activation_sent, name='url_activationSent'),
    path('activate/<slug:uidb64>/<slug:token>', activate, name='activate'),

]

My code for views.py:

from django.contrib.auth import login
from django.contrib.auth.models import User
from django.contrib.sites.shortcuts import get_current_site
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render, redirect
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from contas.tokens import account_activation_token
from .models import Transacao
from .form import TransacaoForm, SignUpForm
from django.core.mail import send_mail
from django.conf import settings

import datetime, time

# Create your views here.


def home(request):
    data = {}
    data["transacoes"] = Transacao.objects.all()
    data["now"] = datetime.datetime.now()
    return render(request, "contas/home.html", data)


def nova_transacao(request):
    form = TransacaoForm(request.POST or None)
    if form.is_valid():
        if request.user.is_authenticated:
            if request.user.is_superuser:
                form.save()
                return redirect('url_home')
            else:
                return redirect('url_notSuper')
        else:
            return redirect('url_login')
    return render(request, "contas/form.html", {"form": form})


def update(request, pk):
    transacao = Transacao.objects.get(pk=pk)
    form = TransacaoForm(request.POST or None, instance=transacao)
    if form.is_valid():
        if request.user.is_authenticated:
            if request.user.is_staff:
                form.save()
                return redirect('url_home')
            else:
                return redirect('url_notSuper')
        else:
            return redirect('url_login')
    return render(request, "contas/form.html", {"form": form, "transacao": transacao})


def delete(request, pk):
    transacao = Transacao.objects.get(pk=pk)
    if request.user.is_authenticated:
        if request.user.is_staff:
            transacao.delete()
            return redirect('url_home')
        else:
            return redirect('url_notSuper')
    else:
        return redirect('url_login')


def signUp(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST or None)
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            current_site = get_current_site(request) 
            subject = 'Ative sua conta Controller-Gastos'
            uid = urlsafe_base64_encode(force_bytes(user.pk)).decode()
            token = account_activation_token.make_token(user)
            activation_link = "{0}/uid={1}/token={2}".format(current_site, uid, token)
            email_from = settings.EMAIL_HOST_USER
            to_email = [form.cleaned_data.get('email')]
            message = "Hello {0},\n {1}".format(user.username, activation_link)
            # send_mail(subject, message, email_from, to_email)
            return HttpResponse('Please confirm your email address to complete the registration using the link below<br>' + message)
    else:
        form = SignUpForm()
    return render(request, 'contas/signUp.html', {'form': form})


def activate(request, uidb64, token):
    try:
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=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.profile.email_confirmed = True
        user.save()
        login(request, user)
        return HttpResponse('Account activated successfully')
        # time.sleep(5)
        # return redirect('url_home')
    else:
        return render(request, 'contas/account_activation_invalid.html')



def notSuper(request):
    return render(request, 'contas/notSuper.html')

def activation_sent(request):
    return render(request, 'contas/activation_sent.html')

My code of contas/activate.html:

{% autoescape off %}
Hi {{ user.username }},
Please click on the link below to confirm your registration:

http://{{ domain }}{% url 'activate' uidb64 token %}
{% endautoescape %}

My code of models.py:

from django.db import models
from django.utils.timezone import now
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)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
email_confirmed = models.BooleanField(default=False)

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

Currently when I register a new user I get the HttpResponse with the activation link, but it does nothing.

Page not found (404)
Request Method:     GET
Request URL:    http://0.0.0.0:8000/uid%3DNTY/token%3D4ze-3028a8e050e89eed45a1

Using the URLconf defined in controle_gastos.urls, Django tried these URL patterns, in this order:

    admin/
    [name='url_home']
    update/<int:pk>/ [name='url_update']
    delete/<int:pk>/ [name='url_delete']
    403/ [name='url_notSuper']
    form/ [name='url_novaTransacao']
    signup/ [name='url_signUp']
    signup/activation_sent/ [name='url_activationSent']
    activate/<slug:uidb64>/<slug:token> [name='activate']

The current path, uid=NTY/token=4ze-3028a8e050e89eed45a1, didn't match any of these.

1 Answers1

0

Based on your urls.py file, your activation link should look like below:

 http://0.0.0.0:8000/activate/NTY/4ze-3028a8e050e89eed45a1

But the url you get in your activation message is:

http://0.0.0.0:8000/uid%3DNTY/token%3D4ze-3028a8e050e89eed45a1

You can fix this by changing the way you are formatting activation_link in the signUp view, which could be done this way:

def signUp(request):
if request.method == 'POST':
    form = SignUpForm(request.POST or None)
    if form.is_valid():
        user = form.save(commit=False)
        user.is_active = False
        user.save()
        current_site = get_current_site(request) 
        subject = 'Ative sua conta Controller-Gastos'
        uid = urlsafe_base64_encode(force_bytes(user.pk)).decode()
        token = account_activation_token.make_token(user)

        # activation_link = "{0}/uid={1}/token={2}".format(current_site, uid, token)
        activation_link = "{0}/activate/{1}/{2}".format(current_site, uid, token)

        email_from = settings.EMAIL_HOST_USER
        to_email = [form.cleaned_data.get('email')]
        message = "Hello {0},\n {1}".format(user.username, activation_link)
        # send_mail(subject, message, email_from, to_email)
        return HttpResponse('Please confirm your email address to complete the registration using the link below<br>' + message)
else:
    form = SignUpForm()
return render(request, 'contas/signUp.html', {'form': form})
ar-m-an
  • 1,551
  • 1
  • 6
  • 4
  • Worked, thank you, but now I have another question: How can I use a html template on the confirmation email? I can send simple mails, but when I try to add a html template it looks like this If you can help me I will be very happy. – Gustavo Luiz Bispo dos Santos Sep 07 '18 at 19:24
  • NOTE: I have eddited the activate.html to be more friendly. So now it gives me the appearence – Gustavo Luiz Bispo dos Santos Sep 07 '18 at 19:34
  • @GustavoLuizBispodosSantos Your question has been already answered here: [Creating email templates with Django](https://stackoverflow.com/questions/2809547/) – ar-m-an Sep 07 '18 at 20:05
  • @GustavoLuizBispodosSantos Btw, if this or any answer has solved your question please consider [accepting it](https://meta.stackexchange.com/q/5234/179419) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. :) – ar-m-an Sep 07 '18 at 20:08