7👍
You need to hook up your own reset password serializer (PASSWORD_RESET_SERIALIZER
) with customized save
method.
(ref: https://github.com/Tivix/django-rest-auth/blob/v0.6.0/rest_auth/serializers.py#L123)
Unfortunately you need to override the whole save method, due to how the e-mail options are used. We we’ll make it a bit more flexible in the next release (0.7.0)
26👍
I recently needed to implement the same thing in one of my projects and could not find a thorough answer anywhere.
So I’m leaving my solution here for anyone who needs it in the future.
Expanding on mariodev’s suggestion:
1. Subclass PasswordResetSerializer
and override save
method.
yourproject_app/serializers.py
from django.conf import settings
from rest_auth.serializers import PasswordResetSerializer as _PasswordResetSerializer
class PasswordResetSerializer(_PasswordResetSerializer):
def save(self):
request = self.context.get('request')
opts = {
'use_https': request.is_secure(),
'from_email': getattr(settings, 'DEFAULT_FROM_EMAIL'),
###### USE YOUR TEXT FILE ######
'email_template_name': 'example_message.txt',
'request': request,
}
self.reset_form.save(**opts)
2. Configure AUTH_USER_MODEL
yourproject/settings.py
###### USE YOUR USER MODEL ######
AUTH_USER_MODEL = 'yourproject_app.ExampleUser'
3. Connect custom PasswordResetSerializer
to override default
yourproject/settings.py
REST_AUTH_SERIALIZERS = {
'PASSWORD_RESET_SERIALIZER':
'yourproject_app.serializers.PasswordResetSerializer',
}
4. Add the path to the directory where your custom email message text file is located to TEMPLATES
yourproject/settings.py
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'yourproject/templates')],
...
}
]
5. Write custom email message (default copied from Django)
yourproject/templates/example_message.txt
{% 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 '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: This solution was written for an older version of django-rest-auth (v0.6.0). As I can tell from the comments, it seems there have been some updates made to the source package that more readily handle custom email templates out-of-box. It is always better to use methods defined in a package rather than overriding them like in my solution. Though once a necessity, it may not be so any longer.
- Django render_to_string() ignores {% csrf_token %}
- How can I disable a model field in a django form
- How to create custom groups in django from group
- How does this Man-In-The-Middle attack work?
12👍
You can inherit PasswordResetSerializer
and override the get_email_options
method. For example:
from rest_auth.serializers import PasswordResetSerializer
class CustomPasswordResetSerializer(PasswordResetSerializer):
def get_email_options(self):
return {
'subject_template_name': 'registration/password_reset_subject.txt',
'email_template_name': 'registration/password_reset_message.txt',
'html_email_template_name': 'registration/'
'password_reset_message.html',
'extra_email_context': {
'pass_reset_obj': self.your_extra_reset_obj
}
}
- How can I test if my redis cache is working?
- How does this Man-In-The-Middle attack work?
- Django's get_current_language always returns "en"
7👍
A simple solution is
Create over templates directory:
-templates
-registration
password_reset_email.html
with content you want.
Django rest-auth use django.contrib.auth templates.
- Is there a way to render a html page without view model?
- How does this Man-In-The-Middle attack work?
7👍
So for the dj-rest-auth
, this is how I did it:
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.urls.base import reverse
from allauth.account import app_settings
from allauth.account.adapter import get_adapter
from allauth.account.utils import user_pk_to_url_str, user_username
from allauth.utils import build_absolute_uri
from dj_rest_auth.forms import AllAuthPasswordResetForm
from dj_rest_auth.serializers import PasswordResetSerializer
class CustomAllAuthPasswordResetForm(AllAuthPasswordResetForm):
def save(self, request, **kwargs):
current_site = get_current_site(request)
email = self.cleaned_data['email']
token_generator = kwargs.get('token_generator',
default_token_generator)
for user in self.users:
temp_key = token_generator.make_token(user)
# save it to the password reset model
# password_reset = PasswordReset(user=user, temp_key=temp_key)
# password_reset.save()
# send the password reset email
path = reverse(
'password_reset_confirm',
args=[user_pk_to_url_str(user), temp_key],
)
url = build_absolute_uri(None, path) # PASS NONE INSTEAD OF REQUEST
context = {
'current_site': current_site,
'user': user,
'password_reset_url': url,
'request': request,
}
if app_settings.AUTHENTICATION_METHOD != app_settings.AuthenticationMethod.EMAIL:
context['username'] = user_username(user)
get_adapter(request).send_mail('account/email/password_reset_key',
email, context)
return self.cleaned_data['email']
class CustomPasswordResetSerializer(PasswordResetSerializer):
@property
def password_reset_form_class(self):
return CustomAllAuthPasswordResetForm
# settings.py
REST_AUTH_SERIALIZERS = {
'PASSWORD_RESET_SERIALIZER':
'api.users.api.serializers.CustomPasswordResetSerializer',
}
By passing None
to build_absolute_uri
instead of the original request
, it will take the value you have in django.contrib.sites
module with SITE_ID=1
. So whatever you have defined as your domain in the Django admin will now be the domain in the reset URL. This makes sense if you want to have the password reset URL point to your frontend, that might be a React application running on a different domain.
Edit:
My PR regarding this issue was merged, with the next release this will be possible to set in your settings. Checkout the docs for dj-rest-auth
to see which setting you need to set.
6👍
if you want to use a html email template, an update to Brian’s answer would be to add
'html_email_template_name': 'account/email/example_message.html',
just below
###### USE YOUR TEXT FILE ######
'email_template_name': 'account/email/example_message.txt',
this way you can the email with a html template
You can see why this happens by inspecting the send_mail
method of the PasswordResetForm class
class PasswordResetForm(forms.Form):
email = forms.EmailField(label=_("Email"), max_length=254)
def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
"""
Send a django.core.mail.EmailMultiAlternatives to `to_email`.
"""
subject = loader.render_to_string(subject_template_name, context)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
body = loader.render_to_string(email_template_name, context)
email_message = EmailMultiAlternatives(subject, body, from_email, [to_email])
if html_email_template_name is not None:
html_email = loader.render_to_string(html_email_template_name, context)
email_message.attach_alternative(html_email, 'text/html')
email_message.send()```
- Paypal monthly subscription plan settings for first day of the month and making monthly recurring payment – django python
- How to emit SocketIO event on the serverside
- How can I schedule a Task to execute at a specific time using celery?
- Create a canonical "parent" product in Django Oscar programmatically
2👍
Create directory with path as following in your template folder
templates/admin/registration/
Now copy all files in django/contrib/admin/templates/registration/ into this directory you just created. You can find this directory where you have installed django. In linux, it can be find here
/usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/registration
You will need root priviliges for accessing this.
Now when you will send email, templates in you just copied in your project will be used.
- Is there a way to render a html page without view model?
- How to upgrade Django on ubuntu?
- How does django-nose differ from the default Django test-runner
- Django render_to_string() ignores {% csrf_token %}
2👍
This link might be helpful. With it I was able to find where the email templates were and how to customize them.
You can find the info at the bottom of the page under
Customize the email message
http://www.sarahhagstrom.com/2013/09/the-missing-django-allauth-tutorial/#Customize_the_email_message
- Changing password in Django Admin
- Django's get_current_language always returns "en"
- Django template indentation guideline
- How do I simulate connection errors and request timeouts in python unit tests
- Accessing django project in LAN systems
1👍
For anyone using all-auth in addition to dj-rest-auth, kindly note that solutions that override get_email_options() will NOT work as dj-rest-auth uses the AllAuthPasswordResetForm from all-auth pkg when it is found under installed_apps in settings. This uses different code than dj-rest-auth to send mails, so the override won’t come into effect. Instead you will have to override the ‘template_prefix’ in the all-auth form and/or update the url as needed by extending the form, in addition to overriding the serializer to use your custom form. This tutorial is a good reference that I found.
Hope it saves someone’s time 🙂
- Installing django 1.5(development version) in virtualenv
- How to create custom groups in django from group