Tivix / django-rest-auth

This app makes it extremely easy to build Django powered SPA's (Single Page App) or Mobile apps exposing all registration and authentication related functionality as CBV's (Class Base View) and REST (JSON)
www.tivix.com
MIT License
2.4k stars 662 forks source link

account-confirm-email raises ImproperlyConfigured #290

Open jokimies opened 7 years ago

jokimies commented 7 years ago

Used relevant pieces:

django-allauth==0.28.0
django-rest-auth==0.8.2
Django==1.10.3
djangorestframework==3.5.3

Created a user with POST request to /rest-auth/registration/ User was created fine, an verification email was send, with a link to verify the email address. However, clinking the link results in error:

Internal Server Error: /rest-auth/registration/account-confirm-email/Ng:1cGlUl:EvPY0Yyu6YHLZEWEtIp/
....
ImproperlyConfigured: TemplateResponseMixin requires either a definition of 'template_name'
 or an implementation of 'get_template_names()'

I believe the error is in rest_auth.registration.urls:

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

Django docs are saying (https://docs.djangoproject.com/en/1.10/ref/class-based-views/base/#templateview) that TemplateView inherits from TemplateResponseMixin, and docs for that (https://docs.djangoproject.com/en/1.10/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin) are telling that 'Not defining a template_name will raise a django.core.exceptions.ImproperlyConfigured exception.' That would suggest that TemplateView.as_view() need template_name argument.

In my urls.py I have

url(r'^rest-auth/', include('rest_auth.urls')),
url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),

i.e I'm not trying to define any own views, just using the provided ones.

If I go and change rest_auth.registration.urls to contain

url(r'^account-confirm-email/(?P<key>[-:\w]+)/$', TemplateView.as_view(template_name='empty.html'),
name='account_confirm_email')

and making sure that django finds that empty.html (which is totally blank), the 'ImproperlyConfigured' exception disappears (but don't known what the template actually should contain)

jokimies commented 7 years ago

Appears this is a feature and reported a few times earlier eg. https://github.com/Tivix/django-rest-auth/issues/15 Maybe a mention in documentation that one should overwrite the view (couldn't see any), maybe same info to documentation as in https://github.com/Tivix/django-rest-auth/issues/15#issuecomment-59034727 ?

okc0mputer commented 7 years ago

I'm working on the same issue. The user is created and the email is sent, but clicking the link gives me the improperly configured error as well. What i'm more interested in getting is the api to verify as well via the 'verify-email/' endpoint. posting the key to the endpoint should have the same effect as clicking the link, correct?

[edit] Got the API working, but it still leaves a few questions...

onekiloparsec commented 7 years ago

Hey there. I'm struggling with all of this as well. And I must say that documentation falls a bit short just before the end of the tutorial...

But I managed to get the right confirmation email view, without any special trick, but rather by noticing two issues, which, taken together, can get you lost for a long time.

First, the regex found in the FAQ (?P<key>[-:\w]+)/$ doesn't work. I personally used this (?P<key>\w+)/$ for a while, found on Stackoverflow probably, and never realised this couldn't be enough. Anyway, both fail, as far as I can tel. This is problematic because the system creates confirmation keys that aren't understood by urls routes.

I personally use (?P<key>[\s\d\w().+-_',:&]+)/$.

Second, if you are like me and have a personal proud to keep things neatly organised, you end up having your urls like that:

from allauth.account.views import confirm_email as allauthemailconfirmation

(...)
    url(r'^rest-auth/', include('rest_auth.urls')),
    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
    url(r'^rest-auth/registration/account-confirm-email/(?P<key>{0})/$'.format(regex.full_string_regex),
        allauthemailconfirmation, name="account_confirm_email"),

But the thing is, the url you request is being caught up by the second url line url(r'^rest-auth/registration/', include('rest_auth.registration.urls')), and fails, before evaluating the last one, which is the one we wants url(r'^rest-auth/registration/account-confirm-email/...! And the failure is precisely the one that triggered this GitHub issue thread.

Hence, you should swap the two url routes, and you're good to go. As a general rule, specific url routes like that should come before more general ones.

My two cents. Hope this helps.

Shelagh-Lewins commented 5 years ago

@onekiloparsec when I try to use your solution I get an error
name 'regex' is not defined How do I import the 'regex' module that you are using?

onekiloparsec commented 5 years ago

The regex module is just a python file I wrote myself, and where I store all my regexes. The only important and relevant part, for the example above, is, in the regex.py file:

full_string_regex = "(?P<key>[\s\d\w().+-_',:&]+)/$"

Shelagh-Lewins commented 5 years ago

Ah, thanks! I got it working with this:

url(r"^rest-auth/registration/account-confirm-email/(?P<key>[\s\d\w().+-_',:&]+)/$", confirm_email,
        name="account_confirm_email"),
Shelagh-Lewins commented 5 years ago

Would you be able to say how to use your regex with the newer re_path syntax? This fails with a syntax error: re_path(r'^rest-auth/registration/account-confirm-email/(?P<key>[\s\d\w().+-_',:&]+)/$', confirm_email, name='account_confirm_email'),

saptami2016 commented 5 years ago

hey i too m also getting same error :from django.urls import include, path from allauth.account.views import confirm_email

as allauthemailconfirmation

from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ path('rest-auth/', include('rest_auth.urls')), path('rest-auth/registration/', include('rest_auth.registration.urls')), path("rest-auth/registration/account-confirm-email/",include('rest_auth.registration.urls') , name="confirm_email"), path('api-token-auth/',obtain_jwt_token), let me know how to ressolve this i know that the error is because of these following only

and the error m getting is : "TemplateResponseMixin requires either a definition of " django.core.exceptions.ImproperlyConfigured: TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()' [01/Apr/2019 06:25:51] "GET /api/v1/rest-auth/registration/account-confirm-email/account-confirm-email/Mjk:1hAqO4:tU562SfhiYl8bf3qgG5uz9THD9E/ HTTP/1.1" 500 93136

EKami commented 5 years ago

As for me I have a separate app to handle this authentication so when I put:

from django.contrib import admin
from django.urls import path, include, re_path

from rest_framework.routers import DefaultRouter
from rest_framework.schemas import get_schema_view
from rest_auth.registration.views import VerifyEmailView

schema_view = get_schema_view(title='API')

urlpatterns = [
    path('', include(router.urls)),
    path('admin/', admin.site.urls),
    path('api/v1/', include('api.urls')),

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

in my project.project.urls module it works, but if I move those lines to project.users.urls I get the:

Reverse for 'account_confirm_email' not found. 'account_confirm_email' is not a valid view function or pattern name.

error. I find it dirty to have the urls handling the email confimation outside my users app, any idea how I can make django look for account_confirm_email in my users app instead of my root app url module? One solution could be to add in project.project.urls:

path('', include('project.users.urls')),

But that's also a dirty solution =/

scientronic92 commented 5 years ago

I managed to solve the issue, in the file: /venv/lib/python3.6/site-packages/rest_auth/registration/urls.py add

from allauth.account.views import confirm_email `

url(r'^account-confirm-email/(?P[-:\w]+)/$', TemplateView.as_view(template_name='empty.html'), name='account_confirm_email'),


url(r"^account-confirm-email/(?P[\s\d\w().+-_',:&]+)/$", confirm_email, name="account_confirm_email"), and you don't need to add the path of auth/registration/confirm-email to project urls, you just need to add path('rest-auth/registration/', include('rest_auth.registration.urls')), ` another issue you might face is redirect to accounts/login, you can redirect to login page using nginx redirect.

elcolie commented 4 years ago

Hey there. I'm struggling with all of this as well. And I must say that documentation falls a bit short just before the end of the tutorial...

But I managed to get the right confirmation email view, without any special trick, but rather by noticing two issues, which, taken together, can get you lost for a long time.

First, the regex found in the FAQ (?P<key>[-:\w]+)/$ doesn't work. I personally used this (?P<key>\w+)/$ for a while, found on Stackoverflow probably, and never realised this couldn't be enough. Anyway, both fail, as far as I can tel. This is problematic because the system creates confirmation keys that aren't understood by urls routes.

I personally use (?P<key>[\s\d\w().+-_',:&]+)/$.

Second, if you are like me and have a personal proud to keep things neatly organised, you end up having your urls like that:

from allauth.account.views import confirm_email as allauthemailconfirmation

(...)
    url(r'^rest-auth/', include('rest_auth.urls')),
    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
    url(r'^rest-auth/registration/account-confirm-email/(?P<key>{0})/$'.format(regex.full_string_regex),
        allauthemailconfirmation, name="account_confirm_email"),

But the thing is, the url you request is being caught up by the second url line url(r'^rest-auth/registration/', include('rest_auth.registration.urls')), and fails, before evaluating the last one, which is the one we wants url(r'^rest-auth/registration/account-confirm-email/...! And the failure is precisely the one that triggered this GitHub issue thread.

Hence, you should swap the two url routes, and you're good to go. As a general rule, specific url routes like that should come before more general ones.

My two cents. Hope this helps.

Django3 Python 3.7 Neither import regex nor from regex import regex works How do solve this issue?

onekiloparsec commented 4 years ago

Django3 Python 3.7 Neither import regex nor from regex import regex works How do solve this issue?

See https://github.com/Tivix/django-rest-auth/issues/290#issuecomment-459437238

elcolie commented 4 years ago

@onekiloparsec Thank you for hinting. I got the answer https://github.com/Tivix/django-rest-auth/issues/290#issuecomment-459447151

Ah, thanks! I got it working with this:

url(r"^rest-auth/registration/account-confirm-email/(?P<key>[\s\d\w().+-_',:&]+)/$", confirm_email,
        name="account_confirm_email"),
MuhammadAnas47 commented 5 months ago

Hello,

Just refer this Demo. It working for me.

https://github.com/MuhammadAnas47/django-rest-auth/tree/master/demo