I have been building a user account functionality for a Django app. In doing so, I have come across a problem and am uncertain of whether I am doing something wrong or have encountered an unfamiliar quirk of Django/Python. Any help is appreciated.
I have the following set of (working) urls (user_accounts/urls.py):
app_name = 'user_accounts'
urlpatterns = [
path('signup', views.UserSignUpView.as_view(), name='signup'),
path('logout', auth_views.LogoutView.as_view(), name='logout'),
path('login', auth_views.LoginView.as_view(template_name='user_accounts/login.html'), name='login'),
re_path(r'^reset/$', auth_views.PasswordResetView.as_view(template_name='user_accounts/password_reset.html', email_template_name='user_accounts/password_reset_email.html', subject_template_name='user_accounts/password_reset_subject.txt'), name='password_reset'),
re_path(r'^reset/done/$', auth_views.PasswordResetDoneView.as_view(template_name='user_accounts/password_reset_done.html'), name='password_reset_done'),
re_path(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.PasswordResetConfirmView.as_view(template_name='user_accounts/password_reset_confirm.html'), name='password_reset_confirm'),
re_path(r'^reset/complete/$', auth_views.PasswordResetCompleteView.as_view(template_name='user_accounts/password_reset_complete.html'), name='password_reset_complete')
]
I have been trying to test it as follows (user_accounts/tests/test_views_forms.py):
class SuccessfulPasswordResetTests(TestCase):
def setUp(self):
email = 'jon#doe.com'
User.objects.create_user(username='john', email=email, password='123abcdef')
url = reverse('user_accounts:password_reset')
print(reverse('user_accounts:password_reset_done'))
self.response = self.client.post(url, {'email': email})
def test_redirection(self):
'''
A valid form submission should redirect to password_reset_done
'''
url = reverse('password_reset_done')
self.assertRedirects(self.response, url)
The issue is that I get the following error:
File
"/home/user-name/sites/project-web/project/user_accounts/tests/test_views_forms.py",
line 128, in setUp
self.response = self.client.post(url, {'email': email})
django.urls.exceptions.NoReverseMatch: Reverse for
'password_reset_done' not found. 'password_reset_done' is not a valid
view function or pattern name.
Yet, when I navigate directly to /user/reset/done/ in the browser, it serves the proper template.
The project's urls.py file looks as follows. Please note that I am using DjangoCMS
from django.contrib import admin
from django.urls import include, path
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('video/', include('video_uploader.urls')),
path('user/', include('user_accounts.urls')),
path('', include('cms.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
You just need to set the success_url attribute in the PasswordResetView. Out of the box it defaults to reverse_lazy('password_reset_done') but since you're using a custom app name the url can't be resolved even though the namespace is the same.
This should do the trick:
re_path(r'^reset/$', auth_views.PasswordResetView.as_view(
template_name='user_accounts/password_reset.html',
success_url=reverse_lazy('user_accounts:password_reset_done'),
email_template_name='user_accounts/password_reset_email.html',
subject_template_name='user_accounts/password_reset_subject.txt'), name='password_reset')
This is a working code. Note the addition of success_url in several paths, which end up working as a cascade. That is one gets triggered after another. I also converted from the regex format to the path format. This may have been needed to get the thing working as well.
from django.urls import path, re_path, reverse_lazy, include
from django.contrib.auth import views as auth_views
from . import views
app_name = 'user_accounts'
urlpatterns = [
path('signup/', views.UserSignUpView.as_view(), name='signup'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('login/', auth_views.LoginView.as_view(template_name='user_accounts/login.html'), name='login'),
path('password-change/', auth_views.PasswordResetView.as_view(template_name='user_accounts/password_reset.html', email_template_name='user_accounts/password_reset_email.html', subject_template_name='user_accounts/password_reset_subject.txt', success_url = reverse_lazy('user_accounts:password_reset_done')), name='password_reset'),
path('password-change/done/', auth_views.PasswordResetDoneView.as_view(template_name='user_accounts/password_reset_done.html'), name='password_reset_done'),
#re_path(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.PasswordResetConfirmView.as_view(template_name='user_accounts/password_reset_confirm.html'), name='password_reset_confirm'),
path('password-change/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='user_accounts/password_reset_confirm.html', success_url = reverse_lazy('user_accounts:password_reset_complete')), name='password_reset_confirm'),
path('password-change/complete/', auth_views.PasswordResetCompleteView.as_view(template_name='user_accounts/password_reset_complete.html'), name='password_reset_complete')
]
Related
I am new to Django. I'm trying to implement jet authentication along with social authentication.
I'm following this tutorial https://jkaylight.medium.com/django-rest-framework-authentication-with-dj-rest-auth-4d5e606cde4d
I tried to implement the same but its not working.
I'm getting this error:
django.urls.exceptions.NoReverseMatch: Reverse for 'account_confirm_email' not found. 'account_confirm_email' is not a valid view function or pattern name.
My project level urls.py
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView
)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# path('account/', include('allauth.urls')),
path('admin/', admin.site.urls),
path('api/user/', include('user.urls')),
path('api/schema/', SpectacularAPIView.as_view(), name='api-schema'),
path(
'api/docs/',
SpectacularSwaggerView.as_view(url_name='api-schema'),
name='api-docs'
),
]
My App level urls.py
from django.urls import path, re_path
from dj_rest_auth.registration.views import RegisterView, VerifyEmailView, ConfirmEmailView
from dj_rest_auth.views import LoginView, LogoutView
from user import views
app_name = 'user'
urlpatterns = [
path('account-confirm-email/<str:key>/', ConfirmEmailView.as_view()),
path('register/', RegisterView.as_view()),
path('login/', LoginView.as_view()),
path('logout/', LogoutView.as_view()),
path('verify-email/',
VerifyEmailView.as_view(), name='rest_verify_email'),
path('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'),
path('listusers/', views.ListUsers.as_view(), name='list-users'),
]
When I try to register a user. It causes this error.
I'm using dj-rest-auth package to implement authentication.
If I replace the email verification related urls from app level to project level. Then everything is working fine.
What is causing this error ?
For the registration part, you have to use allauth which has some baked-in integrations with dj-rest-auth
also, you would have to add some things in your settings.py:
INSTALLED_APPS = [
"dj_rest_auth.registration",
"allauth",
"allauth.account"
]
AUTHENTICATION_BACKENDS = [
"allauth.account.auth_backends.AuthenticationBackend",
"django.contrib.auth.backends.ModelBackend",
]
add these URLs to the urls.py:
urlpatterns = [
path("signup/", include("dj_rest_auth.registration.urls"))
path("verify-email/", VerifyEmailView.as_view(), name="rest_verify_email"),
path(
"account-confirm-email/",
VerifyEmailView.as_view(),
name="account_confirm_email_sent",
),
path(
"account-confirm-email/<key>/",
VerifyEmailView.as_view(),
name="account_confirm_email",
),
]
The request is not getting <str:key>. Please check where you are supplying. It can be from view or template.
I can't seem to find the error, site works fine but when I request http://127.0.0.1:8000/test I get the 404 error, I feel so stupid I'm really stuck on this, please help:(
Error:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/test
Using the URLconf defined in project4.urls, Django tried these URL patterns, in this order:
admin/
[name='index']
login [name='login']
logout [name='logout']
register [name='register']
posts-json/ [name='posts-view-json']
^network/static/(?P<path>.*)$
^media/(?P<path>.*)$
The current path, test, didn’t match any of these.
You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
This is my urls
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from . import views
from .views import post_view_json, profile_test_view
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("test/", profile_test_view, name="test"),
# endpoints
path("posts-json/", post_view_json, name="posts-view-json")
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
It's a social website and I'm trying to render the posts and user's profiles on a page.
My views
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.http.response import JsonResponse
from django.shortcuts import render
from django.urls import reverse
from django.core import serializers
from .models import User, Post, Profile
def index(request):
qs = Post.objects.all()
context = {
'hello': 'hello world!',
'qs':qs,
}
return render(request, "network/index.html", context)
def post_view_json(request):
qs = Post.objects.all()
data = serializers.serialize('json', qs)
return JsonResponse({'data': data})
def profile_test_view(request):
profile = Profile.objects.get(user=request.user)
return render(request, "network/profile_test.html", {'profile':profile})
You have a trailing slash in urls.py but not in the URL you are calling.
Either change urls.py like this:
...
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("test", profile_test_view, name="test"), # <-- NOTE: I removed the slash here
# endpoints
path("posts-json/", post_view_json, name="posts-view-json")
]
...
or call http://127.0.0.1:8000/test/ <-- NOTE: slash added
I want to split the django app urls into two urls with different names, urls.py and reset_urls.py. First one, urls.py works as expected, but the second does not. I tried the obvious approach but it seems not to be working. I want the reset_urls.py to be an endpoint for a password reset, but after creating, it seems not to be working. I know django allows for renaming and having multiple urls.py in single app, but I'm not sure exactly how it should be done, even after checking the docs(not sure I checked the right one)
Here the source code for the urls:
URLconf:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', include('blog.urls', namespace='blog')),
path('accounts/', include('users.urls', namespace='account')),
path('accounts/reset', include('users.reset_urls')),
path('admin/', admin.site.urls),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urls.py
Works as expected. no issue here.
from django.urls import path
from users import views
from django.contrib.auth import views as auth_views
app_name = 'account'
urlpatterns = [
path('profile', views.profile, name='profile'),
path('register', views.register, name='register'),
path('login', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
]
reset_urls.py
Does not work as expected
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password_reset/', auth_views.PasswordResetView.as_view(template_name='users/account/password_reset.html'),
name='password_reset'),
path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/account/password_reset_done.html'),
name='password_reset_done'),
path('password_reset_confirm/<uidb64>/<token>/', auth_views.PasswordResetView.as_view(template_name='users/account/password_reset.html'),
name='password_reset_confirm'),
path('password_reset_complete/', auth_views.PasswordResetView.as_view(template_name='users/account/password_reset.html'),
name='password_reset_complete'),
]
Create an urls folder with __init__.py in it, in app directory. Then seperate your urls as you like into several files in the urls folder.
In __init__.py import your urls like:
from .reset_urls import urlpatterns_reset
from .normal_urls import urlpatterns_normal
urlpatterns = urlpatterns_normal + urlpatterns_reset
I am trying to create 2 extra pages on my Django site, I created the first one with no problem (calendar.html) but when I try to create the second one (actionplan.html) it gives me no error, but when I access xxx/actionplan.html , it shows the calendar.html page... I cannot access xxx/actionplan.html
This is my urls.py:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.views.generic import TemplateView
from django.views.generic.detail import DetailView
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
url(r'xxx', TemplateView.as_view(template_name="calendar.html")),
url(r'^xxx/$', DetailView.as_view(template_name="actionplan.html")),
url(r'^admin/', admin.site.urls),
url(r'^', include('blog.urls'), name="Blog"),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
This is my views.py:
from django.views import generic
from .models import Post
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
class Calendar(generic.DetailView):
model = Post
template_name = 'calendar.html'
class Planoacao(generic.DetailView):
model = Post
template_name = 'actionplan.html'
I have tried:
url(r'^xxx/$', DetailView.as_view(template_name="actionplan.html")),
url(r'^xxx', DetailView.as_view(template_name="actionplan.html")),
url(r'^xxx$', DetailView.as_view(template_name="actionplan.html")),
url(r'xxx', DetailView.as_view(template_name="actionplan.html")),
I am officially out of ideas now... can anyone spot a problem?
The problem is, in your urlpatterns you put the same url two times:
url(r'xxx', TemplateView.as_view(template_name="calendar.html")),
url(r'^xxx/$', DetailView.as_view(template_name="actionplan.html")),
You should add a different url for the two views,
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
url(r'^xxx/plan$', DetailView.as_view(template_name="actionplan.html")),
url(r'xxx', TemplateView.as_view(template_name="calendar.html")),
url(r'^admin/', admin.site.urls),
url(r'^', include('blog.urls'), name="Blog"),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
and you should use path no url and not both
You've given them the same url essentially, yoursite.com/xxx, you could reorder them and put the one with the slash first and that might work but then that would make it a nightmare if you use django's APPEND_SLASH setting.
To fix, make your urls unique
The actionplan.html has nothing to do with your url, its "working" only because the regex for the calendar is just looking for xxx in the given url
I have a problem with django's view "password_reset_done".
When I try to open accounts/reset-password I have this error.
But if I open url accounts/reset-password/done it works.
URLS.PY of "accounts" app
from django.conf.urls import url
from django.contrib.auth.views import login , logout, password_reset,
password_reset_done
from . import views
urlpatterns = [
url(r'^register/$', views.register, name='register'),
url(r'^profile/$', views.profile, name='profile'),
url(r'^profile/prpage/(\d+)/$', views.profile, name='prpage'),
url(r'^profile-edit/$', views.profiledit, name='profile-edit'),
url(r'^login/$', login ,{'template_name':'accounts/login.html'},
name='login'),
url(r'^logout/$', views.logout_view, name='logout'),
url(r'^profile/(?P<proj_id>\d+)/$', views.userprojectpage,
name='userprojectpage'),
url(r'^changepassword/$', views.changepassword, name='changepassword'),
url(r'^reset-password/$', password_reset, name='reset_password'),
url(r'^reset-password/done/$', password_reset_done,
name='password_reset_done'),
]
please help! Thanks in advance)
Add success_url parameter of Class Based View PasswordResetView. This will replace default route of password_reset_done
from django.urls import path, re_path, include, reverse_lazy
path('reset/',PasswordResetView.as_view(
template_name='password_reset.html',
email_template_name='password_reset_email.html',
subject_template_name='password_reset_subject.txt',
...
success_url = reverse_lazy('accounts:password_reset_done')
...
...
),name='password_reset'),
11 there are some change made look like password_reset, password_reset_done not able to import therefore display this error regarding this url https://github.com/django/django/blob/stable/1.11.x/django/contrib/auth/views.py.
There are two way to resolve the error above.
to resolve this error add url(r'', include('django.contrib.auth.urls')), to main urls.py in your project. This will stopped the error and keep your urls in your accounts:
url(r'^reset-password/$', password_reset, name='reset_password'),
url(r'^reset-password/done/$', password_reset_done,
name='password_reset_done'),
I have resolved this error like above and it works fine.
Second way to resolve the error is different than first option above,remove the url(r'', include('django.contrib.auth.urls')), from main urls.py file and in your accounts/urls.py add following url's:
url(r'^reset-password/$', password_reset,
{'template_name':'reset_password.html',
'post_reset_redirect':'accounts:password_reset_done',
'email_template_name': 'reset_password_email.html'},
name='reset_password'),
url(r'^reset-password/done/$', password_reset_done,
{'template_name': 'reset_password_done.html'}, name='password_reset_done'),
url(r'^reset-password/confirm/(?P[0-9A-Za-z]+)-(?P.+)/$',
password_reset_confirm, {'template_name': 'reset_password_confirm.html',
'post_reset_redirect':'accounts:password_reset_complete'},
name='password_reset_confirm'),
This is the second solution and working.
I hope that helps your problem and sorry for delay respond your last comment, I was away.
DilMac