Search code examples
pythondjangodjango-rest-frameworkdjango-allauthdjango-rest-auth

how to verify emails after link is clicked usind django rest auth


I am using Django rest auth to authenticate users in my app, the users are successfully getting the email to verify their account but on clicking the link, they get an error

KeyError at /account-confirm-email/MTU:1iNTcO:lRoljcqAs3HQMlyy9AzUJH6Kq5w/

Please, how can the users be successfully verified when they click the link

my settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'rest_auth.registration',
    'allauth',
    'allauth.account',
    'users',
]

ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400 # 1 day in seconds
ACCOUNT_LOGOUT_REDIRECT_URL ='/accounts/login/'
LOGIN_REDIRECT_URL = '/accounts/profile'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'testE'
DEFAULT_FROM_EMAIL = '[email protected]'
DEFAULT_TO_EMAIL = EMAIL_HOST_USER

EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/

urls.py

from rest_auth.registration.views import VerifyEmailView


urlpatterns = [
    path('admin/', admin.site.urls),
    url('api/rest-auth/', include('rest_auth.urls')),
    url('api/account/', include('users.api.urls')),
    url('api/rest-auth/registration/', include('rest_auth.registration.urls')),
    re_path(r'^account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),
    re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$', VerifyEmailView.as_view(), name='account_confirm_email'),
]

[update] the updated traceback after implementing the solution

Traceback:

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  145.                 response = self.process_exception_by_middleware(e, request)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  143.                 response = response.render()

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\response.py" in render
  106.             self.content = self.rendered_content

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\response.py" in rendered_content
  83.         content = template.render(context, self._request)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\backends\django.py" in render
  61.             return self.template.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  171.                     return self._render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in _render
  163.         return self.nodelist.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  937.                 bit = node.render_annotated(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render_annotated
  904.             return self.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in _render
  163.         return self.nodelist.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  937.                 bit = node.render_annotated(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render_annotated
  904.             return self.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in _render
  163.         return self.nodelist.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  937.                 bit = node.render_annotated(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render_annotated
  904.             return self.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\loader_tags.py" in render
  62.                 result = block.nodelist.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  937.                 bit = node.render_annotated(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render_annotated
  904.             return self.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\defaulttags.py" in render
  309.                 return nodelist.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render
  937.                 bit = node.render_annotated(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\base.py" in render_annotated
  904.             return self.render(context)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\template\defaulttags.py" in render
  443.             url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\urls\base.py" in reverse
  90.     return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\ProfilesAPI\venv\lib\site-packages\django\urls\resolvers.py" in _reverse_with_prefix
  673.         raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /account-confirm-email/MTk:1iNcyz:wyyIWJiSWJ2s9JHabdympHnzbMU/
Exception Value: Reverse for 'account_email' not found. 'account_email' is not a valid view function or pattern name.

Solution

  • I believe it is an issue with URLs which is causing your problem. Specifically these two:

    re_path(r'^account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),
    re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$', VerifyEmailView.as_view(), name='account_confirm_email'),
    

    On the first URL you are missing the $. Therefore the first URL is being used for your confirmation link /account-confirm-email/MTU:1iNTcO:lRoljcqAs3HQMlyy9AzUJH6Kq5w/ instead of the second URL which captures the regex named group key. Because you are falling into the first URL the regex capture group key is never set. Subsequently when you are in your view the kwarg['key'] has never been set.

    The solution is to change the urls to be:

    from rest_auth.registration.views import VerifyEmailView
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        url('api/rest-auth/', include('rest_auth.urls')),
        url('api/account/', include('users.api.urls')),
        url('api/rest-auth/registration/', include('rest_auth.registration.urls')),
    
        # note the $ symbol at the end of the regex
        re_path(r'^account-confirm-email/$', VerifyEmailView.as_view(), name='account_email_verification_sent'),
        re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$', VerifyEmailView.as_view(), name='account_confirm_email'),
    ]