how to change the Django password reset email style and content - django

So I'm using the built-in Django password reset system. It works fine, but I'm not satisfied with the email sent to the users. I want to change all of it, from styles to texts. But how am I supposed to do that? I have read some solutions here, but they are more confusing than being helpful.

You can edit the existing email here: <projectName>/lib/python/site-packages/django/contrib/admin/templates/registration/password_reset_email.html
Or you can create an new folder called registration and add the templates to it to create your own:
password_reset_form.html
password_reset_subject.txt
password_reset_email.html
password_reset_done.html
password_reset_confirm.html
password_reset_complete.html
and then include all auth views to your projets url's:
urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]

Related

Context not passed to overwritten templates

Django version 3.2.4
I'm trying to change the default index_title, site_header, and site_title used by the admin site. I've tried all the suggestions here, but the login page refuses to use the updated values. In fact, the required context (site_header in the example below) is empty (confirmed by overriding the template and using the {{ debug }} variable as described here) and the "default" value of "Django administration" is being used. A line from the template C:\Program Files\Python38\Lib\site-packages\django\contrib\admin\templates\admin\base_site.html:
<h1 id="site-name">{{ site_header|default:_('Django administration') }} a</h1>
I currently have all three variables overwritten in my app's admin.py file, and the updated values are being used after I've logged in, but it doesn't work on the initial login page:
admin.site.site_header = 'My Site Header'
admin.site.index_title = 'My Index Title'
admin.site.site_title = 'My Site Title'
I can override the base_site.html template and hardcode a value, but I would like to understand why that is necessary and figure out how I can pass some context to that overwritten template. I've tried all the methods of overriding the original context described here to no avail. That includes having a custom admin site which overrides the default admin site. I've also noticed that the each_context method is not being called on the initial login page, but it is called after I have logged in and I'm viewing an admin page.
I think some of the problem may stem from how I have my urlpatterns set up in urls.py. I have it set up like this so the URL displayed in the address bar for a login is the same for both the admin and non-admin portions of the site.
urlpatterns = [
path('', include('my_app.urls')),
path('login', auth_views.LoginView.as_view(template_name='admin/login.html')),
path('login/', auth_views.LoginView.as_view(template_name='admin/login.html')),
path('logout', auth_views.LogoutView.as_view()),
path('logout/', auth_views.LogoutView.as_view()),
path('admin/login', generic_views.RedirectView.as_view(url='/admin', permanent=True, query_string=False)),
path('admin/login/', generic_views.RedirectView.as_view(url='/admin', permanent=True, query_string=False)),
path('admin/logout', auth_views.LogoutView.as_view()),
path('admin/logout/', auth_views.LogoutView.as_view()),
path('admin/', admin.site.urls)
]
I'm also exclusively using the django_auth_ldap.backend.LDAPBackend:
AUTHENTICATION_BACKENDS = [
'django_auth_ldap.backend.LDAPBackend'
]
Any guidance would be appreciated.
I got around my problem by creating the following context processor:
from django.contrib import admin
def global_context(request):
"""
This is intended to be a global context processor. Any templates rendered from views using the
`django.template.RequestContext` context (the default context used by generic views) will have this context
available to them.
"""
context = {
'index_title': admin.site.index_title,
'site_header': admin.site.site_header,
'site_title': admin.site.site_title
}
return context
This in conjunction with setting admin.site.index_title, admin.site.site_header, and admin.site.site_title to the desired values in admin.py got things working as expected.

Change URL Of Overridden Templates

On my website users access their accounts by going to the following address:
http://127.0.0.1:8000/users_area/username/profile
There they will find a button 'change password' (an overridden django template) which will take them to:
http://127.0.0.1:8000/accounts/password/change/
It is very small and I'm probably being too picky but is it possible to keep this overridden template but change its url? I'd instead like the change password url to be something like:
http://127.0.0.1:8000/users_area/username/password/change/
I've tried creating a template within my user's app, copying the 'change password' template content into there, then linking to it rather than to the overridden 'change password' template, but (obviously, in hindsight) it doesn't work.
I'll add as a side note. I actually have two user types, users and powerusers. Each has a unique and rather different 'users_area':
http://127.0.0.1:8000/users_area/username/profile
and
http://127.0.0.1:8000/powerusers_area/username/profile
If I get an answer to my above question I'm actually hoping to apply it to both of my different user types (shouldn't be hard but thought I should mention it).
Thank you.
In case you want to customize them, even have a customized MyUser model, you can still re-use a lot from Django like this
# authentication
path('user_register', user_register_view, name='user_register'),
path('login', login_view, name='login'),
path('logout', logout_view, name='logout'),
path('change_password', change_password_view, name='change_password'),
path('reset_password/',
auth_views.PasswordResetView.as_view(template_name="MyUser/password_reset.html"),
name="reset_password"),
path('reset_password_sent/',
auth_views.PasswordResetDoneView.as_view(template_name="MyUser/password_reset_sent.html"),
name="password_reset_done"),
path('reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name="MyUser/password_reset_form.html"),
name="password_reset_confirm"),
path('reset_password_complete/',
auth_views.PasswordResetCompleteView.as_view(template_name="MyUser/password_reset_done.html"),
name="password_reset_complete"),
path('profile/<username>', profile_view, name='profile'),
You can do something like this
urls.py
from django.contrib.auth import views as auth_views
urlpatterns = i18n_patterns(
# other URLS
path('/users_area/username/password/change/', auth_views.PasswordChangeView.as_view, name='change_password'),
# more URLS from auth?
)

django-rest-auth password reset sending wrong domain in email

I'm trying to test my password reset configuration on my localhost using django-rest-auth. The email verification and registration work, and I can trigger a password reset event and send an email, but the email contains the wrong domain. Right now it is passing a link containing my-site.com as the domain instead of 0.0.0.0:8000 as the domain. I am running the app inside a docker container which is why it is 0.0.0.0:8000 instead of 127.0.0.1:8000.
Current result:
You're receiving this email because you requested a password reset for your user account at My Site.
Please go to the following page and choose a new password:
http://my-site.com/auth/password-reset/confirm/OA/55d-7dc2614593146ac3ce82/
Your username, in case you've forgotten: testaccount
Thanks for using our site!
The My Site team
Expected result
You're receiving this email because you requested a password reset for your user account at My Site.
Please go to the following page and choose a new password:
http://0.0.0.0:8000/auth/password-reset/confirm/OA/55d-7dc2614593146ac3ce82/
Your username, in case you've forgotten: testaccount
Thanks for using our site!
The My Site team
My url file for my registration is:
from django.urls import path, include
from allauth.account.views import ConfirmEmailView
from . import views
urlpatterns = [
path('registration/account-email-verification-sent/', views.null_view, name='account_email_verification_sent'),
path('registration/account-confirm-email/<key>', ConfirmEmailView.as_view(), name='account_confirm_email'),
path('registration/complete/', views.complete_view, name='account_confirm_complete'),
path('password-reset/confirm/(<uidb64>/<token>/', views.null_view, name='password_reset_confirm'),
path('', include('rest_auth.urls')),
path('registration/', include('rest_auth.registration.urls')),
]
I ran across another post that suggested changing the site id, but I'm not sure this is correct.
How do I get it to pass the currently served domain instead of the site id domain?
Easy Solution
Step 1: Go to /admin/sites/site/, You'll see something similar as below,
Step 2: Edit the existing entry with following value then save it
Domain name: 0.0.0.0:8000
Display name: Your Site Name

Reverse for 'password_reset_confirm'

Django==1.11.2
django-registration-redux==1.6
When I'm trying to reset password (http://localhost:8000/accounts/password/reset/), I occur at a page with headline Django administration, and breadcrumbs below: Home › Password reset. So, this is a part of Django functionality. This may be important, though, I don't know how. But anyway, this is not the functionality of django-registration-redux.
I input an email. And get this:
Reverse for 'password_reset_confirm' not found. 'password_reset_confirm' is not a valid view function or pattern name.
In django-registration-redux another name is used. Namely auth_password_reset_confirm.
Well, could you give me a kick here? My settings are below:
settings.py
INCLUDE_REGISTER_URL = True
INCLUDE_AUTH_URLS = True
urls.py
urlpatterns = [
url(r'^accounts/', include('registration.backends.default.urls')),
}
As mentioned in the bug report, registration must be earlier in order then admin. Not entirely sure why and apparently it's hard to fix, as this package is maintained by several Django core team members :).
From the docs, https://django-registration.readthedocs.io/en/2.2/quickstart.html#quickstart: django.contrib.auth must be in INSTALLED_APPS, I suggest adding before registration so that the package can override the core

Django password reset stuck in loop

I am trying to add a user reg system to my Django site. Obviously, I want to use the built-in auth views and forms. I am going about implementing the auth password reset process. It works fine up to sending the email, but then does not redirect properly. The end result is the password reset done email being sent over and over and over. I am overriding the templates, but nothing else, right now all they have is:
{{form.As_p}}
I have changed my urls.py to use the auth.views as such:
from django.contrib.auth import views as auth_views
(r'^account/forgot/$',
auth_views.password_reset,
{'template_name': 'registration/password_reset.html',
'post_reset_redirect':'/account/password-reset-done'}
),
(r'^account/password-reset-done/$',
auth_views.password_reset_done,
{'template_name': 'registration/password_reset_done.html'}
),
It looks to me as though you need a trailing slash on the post_reset_redirect url. Have you tried that? At the moment, /account/password-reset-done won't match r'^account/password-reset-done/$' because the / in that is compulsory.
See example request 4 in the Django url dispatcher documentation: https://docs.djangoproject.com/en/dev/topics/http/urls/#example