I am using the PasswordResetView of django.contrib.auth.views. I am trying to direct my path('reset-password/'...) to use my 'rest_password_email.html' template after the user has submitted an email address for password reset. I have added this as a kwargs, however django is not recognizing it and continues to direct the application to default 'password_reset_email.html'. Any suggestions on how this can be achieved? thanks.
BTW: I am using namespace 'accounts'. Hence the reason for doing the above is to introduce the amended url in my template to account for the namespace.
url.py
from django.urls import path
from . import views
from django.contrib.auth.urls import urlpatterns
from django.contrib.auth.views import (
LoginView, LogoutView,
PasswordResetView, PasswordResetDoneView,
PasswordResetConfirmView,
PasswordResetCompleteView
)
from django.urls import reverse_lazy
app_name = 'accounts'
urlpatterns = [
path('', views.home, name = 'home'),
path('column/', views.column),
path('login/', LoginView.as_view(template_name='accounts/login.html'), name = 'login'),
path('logout/', LogoutView.as_view(template_name='accounts/logout.html'), name = 'logout'),
path('register/', views.register, name = 'register'),
path('profile/', views.view_profile, name = 'view_profile'),
path('profile/edit/', views.edit_profile, name = 'edit_profile'),
path('change_password/', views.change_password, name = 'change_password'),
path('reset-password/', PasswordResetView.as_view(template_name='accounts/reset_password.html'), kwargs={'email_template_name':'accounts/reset_password_email.html','post_reset_redirect': reverse_lazy('accounts:password_reset_done')}, name = 'password_reset'),
path('reset-password/done', PasswordResetDoneView.as_view(), name = 'password_reset_done'),
path('reset-password/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', PasswordResetConfirmView.as_view(), name = 'password_reset_confirm'),
path('reset-password/complete/$', PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]
reset_password_email.html
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'accounts:password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans 'Your username, in case you’ve forgotten:' %} {{ user.get_username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}
You can set your email_template_name in PasswordResetView,
url(r'^reset-password/$',
PasswordResetView.as_view(template_name='accounts/reset_password.html'),
{
'email_template_name': 'accounts/reset_password_email.html',
'success_url' : reverse_lazy('accounts:reset_password_done')
},
name='reset_password'),
or you can directly pass it in .as_view()
url(r'^reset-password/$',
PasswordResetView.as_view(template_name='accounts/reset_password.html',
email_template_name = 'accounts/reset_password_email.html',
success_url = reverse_lazy('accounts:reset_password_done')) ,
name='reset_password'),
The connection error issue is resolved and the reset password is working now. I was missing an Email backend in settings.py. Included: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Related
I have found many similar questions to this issue. This question was one of them, but it didn't solve my problem, so I will ask my own question.
I'm making a password reset page on my website. But when I go to http://localhost:8000/users/reset-password and enter my email and clicks on 'Reset my password', then Django throws a NoReverseMatch error at me.
The error is:
NoReverseMatch at /users/reset-password/
Reverse for 'password_reset_confirm' not found. 'password_reset_confirm' is not a valid view function or pattern name.
I believe there's something wrong with how I write my urlpatterns.
I've tried:
Making my own views and templates.
Rewriting all my urlpatterns.
My Code
urls.py:
"""Defines URL Patterns for users."""
from django.urls import re_path
from django.contrib.auth.views import (
LoginView, PasswordResetView, PasswordResetConfirmView,
PasswordResetDoneView,
)
from . import views
urlpatterns = [
# Login Page.
re_path(r'^login/$', LoginView.as_view(template_name='users/login.html'),
name='login'),
# Logout Page.
re_path(r'^logout/$', views.logout_view, name='logout'),
# Registration Page.
re_path(r'^register/$', views.register, name='register'),
# Password reset Page.
re_path(r'^password_reset/$', PasswordResetView.as_view(
# This is the only line I added in this file.
template_name='users/password_reset_email.html'
),
name='password_reset'),
# Password reset done Page.
re_path(r'^password_reset/done/$', PasswordResetDoneView.as_view(),
name='password_reset_done'),
# Password reset confirm Page.
re_path(r'^password_reset/confirm/'
+ '(?P<uidb64>[0-9A-Za-z]+)/(?P<token>.+)/$',
PasswordResetConfirmView.as_view(),
name='password_reset_confirm'),
]
My own users/password_reset_email.html:
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'users:password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}
Update:
I got something right. Now I get a NoReverseMatch at /users/password_reset/
Reverse for 'password_reset_confirm' with keyword arguments '{'uidb64': '', 'token': ''}' not found. 1 pattern(s) tried: ['users/password_reset/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$']. I got to this error by using my own template of djangos password_reset_email.html, where I modified the line: {% url 'password_reset_confirm' uidb64=uid token=token %} to {% url 'users:password_reset_confirm' uidb64=uid token=token %}. Now i'm almost certain that i'm just writing my urls or regexes wrong.
I have edited my question to show the new code.
I finally got it.
Here is the answer to the problem.
Now I get a ConnectionRefusedError, which means that I now only need to set up an SMTP Server for emails, and then it should work! The thing I was missing all the time was, that I wasn't pointing out what email template I wanted to use. I just set the email template as the template, so Django couldn't render it correctly. Here is the updated code for urls.py where path(r'password-reset/') is changed:
from django.urls import path, reverse_lazy
import django.contrib.auth.views as auth_views
from . import views
urlpatterns = [
# Login Page.
path(r'login/', auth_views.LoginView.as_view(
template_name='users/login.html'
),
name='login'),
# Logout Page.
path(r'logout/', views.logout_view, name='logout'),
# Registration Page.
path(r'register/', views.register, name='register'),
# Password reset page.
path(r'password-reset/', auth_views.PasswordResetView.as_view(
email_template_name='users/password_reset_email.html',
success_url=reverse_lazy('users:password_reset_done')
), name='password_reset'),
# Password reset done page.
path(r'password-reset/done/',
auth_views.PasswordResetDoneView.as_view(),
name='password_reset_done'),
# Password reset confirm page.
path(r'password-reset/confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm')
]
Everything else is correct.
I got the answer from this answer.
i'm using the django built in authentication system and in my login template i have this code :
login.html:
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
{% if user.is_authenticated%}
you are already logged in
{% else %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endif %}
{% endblock %}
but what i really want to do is to redirect the user to the home page if he tries to access login page while already logged in, but i am new to django so i don't know how to do that.
For django>=1.11 you can set redirect_authenticated_user parameter to True in its url in url_patterns to do the redirect, like this:
from django.contrib.auth import views as auth_views
urlpatterns = [
url(r'^login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]
read the document for more information.
and also set LOGIN_REDIRECT_URL in your setting file to your index url or its name:
LOGIN_REDIRECT_URL = '/index/'
In your `settings.py' add this:
LOGIN_REDIRECT_URL = 'index'
if the url name of your index is 'index', else put the correct url name
You can do it in your views.py file.
def login(request):
if request.method =="get":
if request.user.is_authenticated:
return render(// youre code)
I'm having this error message after trying to change my app's password.
Do you have any idea of what's causing this route to fail?
Actually, it is changing the password but it isn't rendering the success template "password_change_done.html".
Thanks!
app/urls.py
from django.contrib.auth import views as auth_views
from django.urls import path
from . import views
app_name = 'account'
urlpatterns = [
# path('login/', views.user_login, name='login'),
path('', views.dashboard, name='dashboard'),
# login / logout urls
path('login/', auth_views.LoginView.as_view(template_name='registration/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('logout-then-login/', auth_views.logout_then_login, name='logout_then_login'),
# change password urls
path('password-change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
]
ERROR MESSAGE
# NoReverseMatch at /account/password-change/
# Reverse for 'password_change_done' not found. 'password_change_done' is not a valid view function or pattern name.
# Request Method: POST
# Request URL: http://localhost:8000/account/password-change/
# Django Version: 2.0.4
# Exception Type: NoReverseMatch
# Exception Value:
# Reverse for 'password_change_done' not found. 'password_change_done' is not a valid view function or pattern name.
# Exception Location: C:\env\django_social_website\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 632
# Python Executable: C:\env\django_social_website\Scripts\python.exe
# Python Version: 3.6.3
# Python Path:
# ['C:\\Projects\\django_social_website',
# 'C:\\env\\django_social_website\\Scripts\\python36.zip',
# 'C:\\ProgramData\\Anaconda3\\DLLs',
# 'C:\\ProgramData\\Anaconda3\\lib',
# 'C:\\ProgramData\\Anaconda3',
# 'C:\\env\\django_social_website',
# 'C:\\env\\django_social_website\\lib\\site-packages',
# 'C:\\env\\django_social_website\\lib\\site-packages\\setuptools-28.8.0-py3.6.egg',
# 'C:\\env\\django_social_website\\lib\\site-packages\\pip-9.0.1-py3.6.egg']
# Server time: Thu, 5 Apr 2018 21:34:22 +0000
app/templates/registration/password_change_form.html
{% extends "base.html" %}
{% block title %}Change your password{% endblock %}
{% block content %}
<h1>Change your password</h1>
<p>Use the form below to change your password.</p>
<form action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Change"></p>
</form>
{% endblock %}
app/templates/registration/password_change_done.html
{% extends "base.html" %}
{% block title %}Password changed{% endblock %}
{% block content %}
<h1>Password changed</h1>
<p>Your password has been successfully changed.</p>
{% endblock %}
Thanks for your help!
I think the problem here is, as Tobit hints, is that your URLs are using an application namespace called account. That has been defined by the presence of app_name = 'account' in your urls.py.
The PasswordChangeView does not expect a namespace when looking up the password_change_done view. However, you can override that in your urls.py by specifying an explicit success_url attribute:
from django.urls import reverse_lazy
# change password urls
path('password-change/', auth_views.PasswordChangeView.as_view(success_url=reverse_lazy('account:password_change_done')), name='password_change'),
More info on namespaces: https://docs.djangoproject.com/en/2.0/topics/http/urls/#url-namespaces-and-included-urlconfs
It works for me:
# account urls.py
from django.urls import path, include
from django.contrib.auth import views as auth_views
from . import views
from django.urls import reverse_lazy
app_name = 'account'
urlpatterns = [
#Password Changes URLs
path('password_change/', auth_views.PasswordChangeView.as_view(
success_url=reverse_lazy('account:password_change_done')
), name='password_change'),
path('password_change/done/',auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
]
The main link is here:
https://django.fun/en/qa/11928/
I'm fairly new to django and I'm currently rewriting the django login views so I can move all the authentication process to a dedicated django app where I can redefine the templates.
So currently I have an accounts app which url.py looks like that:
from django.contrib.auth import views as auth_views
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('login/', auth_views.login, {'template_name': 'accounts/login.html'}, name='login'),
path('logout/', auth_views.logout, name='logout'),
path('password_reset/', auth_views.password_reset,
{'template_name': 'accounts/password_reset_form.html',
'email_template_name': 'accounts/password_reset_email.html',
'subject_template_name': 'accounts/password_reset_subject.txt',
'post_reset_redirect': 'done/'}, name='password_reset'),
path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(
template_name='accounts/password_reset_done.html'), name='password_reset_done'),
path('reset/<uidb64>/<token>/', auth_views.password_reset_confirm,
{'template_name': 'accounts/password_reset_confirm.html',
'post_reset_redirect': '/accounts/reset/done/'}, name='password_reset_confirm'),
path('reset/done/', auth_views.PasswordResetCompleteView.as_view(
template_name='accounts/password_reset_complete.html'), name='password_reset_complete')
]
And a accounts/password_reset_email.html which looks like this:
{% autoescape off %}
To initiate the password reset process for your {{ user.get_username }} account,
click the link below:
{{ protocol }}://{{ domain }}{% url 'accounts:password_reset_confirm' uidb64=uid token=token %}?origin_page={{ request.POST.origin_page }}"
...
Sincerely,
The Team
{% endautoescape %}
What I want to do is to recover the origin_page argument so when the user click on the reset link from the email he get redirected to the right webpage after his password is reset. So far I tried to do this in password_reset_form.html:
{% block content %}
<p>Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one.</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="origin_page" value="{{ request.GET.origin_page }}"/>
<button type="submit">Submit</button>
</form>
{% endblock %}
Here I just want to pass in my origin_page to the submit form so that I can retrieve it from accounts/password_reset_email.html, the url for this page looks like this http://127.0.0.1:8000/accounts/password_reset/?origin_page=/mypage/.
How can I recover the request.POST.origin_page parameter from accounts/password_reset_email.html?
Thanks.
maybe that helps
path('password-reset/',
auth_views.PasswordResetView.as_view(
template_name='form.html',
email_template_name='email.html',
extra_email_context={
'origin_page':'origin_page_thing'
}
),
name='password_reset'),
email:
{{ protocol }}://{{ domain }}{% url 'accounts:password_reset_confirm' uidb64=uid token=token %}?origin_page={{ origin_page }}
E-Kami solution:
Ok I've got it, I actually created a new PasswordResetView like this: ' \
class PasswordResetView(auth_views.PasswordResetView):
template_name = 'commons/password_reset_form.html'
email_template_name = 'commons/password_reset_email.html'
subject_template_name = 'commons/password_reset_subject.txt'
success_url = 'done/'
def post(self, request, *args, **kwargs):
self.extra_email_context = {
'origin_page': self.request.POST['origin_page']
}
return super().post(request, *args, **kwargs)
Django version 1.11.5,
views.py
class SignupPage(CreateView):
form_class = forms.UserSignupForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
website/urls.py
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from django.contrib.auth.views import LoginView,LogoutView
from . import views
app_name = 'website'
urlpatterns = [
url(r'^login/', auth_views.LoginView.as_view(template_name='signin_2_w.html'), name='login'),
url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'),
url(r'^signup/', views.SignupPage.as_view(), name='sign_up'),
forms.py
class UserSignupForm(UserCreationForm):
class Meta:
fields = ('username','email','password1','password2')
model = get_user_model()
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = "Display Name"
self.fields['email'].label = "Email Address"
self.fields['password1'].label = "Password"
self.fields['password2'].label = "Confirm Password"
proj/urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.HomePage.as_view(),name='home'),
url(r'^website/',include('website.urls',namespace='website')),
url(r'^website/',include('django.contrib.auth.urls')),
url(r'^website/',views.StreamyePage.as_view(),name='streamye'),
url(r'^thanks/$',views.ThanksPage.as_view(),name='thanks'),
url(r'^congrats/$',views.CongratsPage.as_view(),name='congrats'),
url(r'^aboutus/$',views.AboutusPage.as_view(),name='about_us'),
HTML
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li>Logout</li>
{% else %}
<li>Login</li>
<li>Signup</li>
{% endif %}
</ul>
In the above code, the signup page is throwing me a error -- "django.urls.exceptions.NoReverseMatch: Reverse for 'sign_up' not found. 'sign_up' is not a valid view function or pattern name."
Please someone help me out where im wrong!
Thanks in advance!
You have to fix the links in the template to target the website urls :
{% if user.is_authenticated %}
<li>Logout</li>
{% else %}
<li>Login</li>
<li>Signup</li>
{% endif %}
In my case, the reason was that the session cookie was corrupted due to code changes.
I solved it by opening my app url in the incognitio mode(which will create fresh session cookie),
Then try non-incognitio normal url login.
If you are using Django rest framework, this may help.
When you have router as,
router.register("path", SomeViewSet, basename="some-name")
Call the reverse as,
reverse("some-name-list")