It seems to me django only supports plain text messages for password reset emails out of the box. How can I use html templates for this purpose?
在我看来,django只支持纯文本消息,用于开箱即用的密码重置电子邮件。我怎样才能将html模板用于此目的?
8 个解决方案
#1
6
Here is how you can do the override:
urls.py
urls.py
url(r'^user/password/reset/$',
'YOUR_APP.views.password_reset',
{'post_reset_redirect' : '/#/login?resetemail=true'},
name="password_reset"),
views.py
views.py
from django.contrib.auth.views import password_reset as django_password_reset
from YOUR_APP.forms import CustomPasswordResetForm
def password_reset(*args, **kwargs):
"""
Overriding the Email Password Resert Forms Save to be able to send HTML email
"""
kwargs['password_reset_form'] = CustomPasswordResetForm
return django_password_reset(*args, **kwargs)
form.py
form.py
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator
class CustomPasswordResetForm(PasswordResetForm):
"""
Overriding the Email Password Resert Forms Save to be able to send HTML email
"""
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
use_https=False, token_generator=default_token_generator, request=None, email_subject_name='registration/password_reset_subject.txt', **kwargs):
from django.core.mail import EmailMultiAlternatives
from django.utils.html import strip_tags
from django.template.loader import render_to_string
from django.contrib.sites.models import get_current_site
from django.utils.http import int_to_base36
for user in self.users_cache:
if not domain_override:
current_site = get_current_site(request)
site_name = current_site.name
domain = current_site.domain
else:
site_name = domain = domain_override
c = {
'email': user.email,
'domain': domain,
'site_name': site_name,
'uid': int_to_base36(user.id),
'user': user,
'token': token_generator.make_token(user),
'protocol': use_https and 'https' or 'http',
}
render = render_to_string(email_template_name, c)
render_subject = render_to_string(email_subject_name, c)
msg = EmailMultiAlternatives(render_subject, strip_tags(render), None, [user.email])
msg.attach_alternative(render, "text/html")
msg.send()
#2
5
You can override save
method of django.contrib.auth.forms.PasswordResetForm
and pass new form as an argument to password_reset
view.
您可以覆盖django.contrib.auth.forms.PasswordResetForm的save方法,并将新表单作为参数传递给password_reset视图。
#3
0
After some amount of trial and error, I discovered a much, much more terse way to supply a custom templated password reset email in the latest version of Django (1.8).
经过一些试验和错误后,我发现了一种更简洁的方式来在最新版本的Django(1.8)中提供自定义模板化密码重置电子邮件。
In your project/urls.py
, add these imports:
在您的project / urls.py中,添加以下导入:
from django.contrib.auth import views as auth_views
from django.core.urlresolvers import reverse_lazy
And add the following route in your urlpatterns before the usual django contrib auth url route inclusion:
并在通常的django contrib auth url route包含之前在urlpatterns中添加以下路由:
url(r'^accounts/password/reset/$',
auth_views.password_reset,
{
'post_reset_redirect': reverse_lazy('auth_password_reset_done'),
'html_email_template_name': 'registration/password_reset_html_email.html'
},
name='auth_password_reset'),
url('^', include('django.contrib.auth.urls')),
And then, in your app's templates/registration
folder, create the password_reset_html_email.html
with whatever HTML template you want.
然后,在您的应用程序的模板/注册文件夹中,使用您想要的任何HTML模板创建password_reset_html_email.html。
The reason this seemed necessary lay in the source for django/contrib/auth/views.py
, which has the view function the original URL route is mapped to:
这似乎是必要的原因在于django / contrib / auth / views.py的源代码,它具有原始URL路由映射到的view函数:
147 def password_reset(request, is_admin_site=False,
148 template_name='registration/password_reset_form.html',
149 email_template_name='registration/password_reset_email.html',
150 subject_template_name='registration/password_reset_subject.txt',
151 password_reset_form=PasswordResetForm,
152 token_generator=default_token_generator,
153 post_reset_redirect=None,
154 from_email=None,
155 current_app=None,
156 extra_context=None,
157 html_email_template_name=None):
158
The html_email_template_name
is set to None
as default, and there didn't seem to be a way to assign its value, aside from rewriting this specific route for this case as I mentioned above.
默认情况下,html_email_template_name设置为None,除了为此情况重写此特定路由之外,似乎没有办法分配其值,如上所述。
Hopefully this helps without needing to copy-paste a bunch of nearly-identical code like some of the other answers suggested - feedback is welcome, of course!
希望这有助于无需复制粘贴一堆几乎完全相同的代码,如建议的其他一些答案 - 当然欢迎反馈!
#4
0
For me the research was time consuming but the solution rather trivial. No overrides no fiddling with forms or anything like that am using Django==1.8.6 but should work from at least django 1.7 onward. To enable support for html formatted emails in password_reset all I had to do is change the email template key name in reset function from email_template_name='emails/password_reset_email_html.html
对我来说,研究耗费时间,但解决方案相当微不足道。没有覆盖没有摆弄表格或类似的东西使用Django == 1.8.6,但至少应该从django 1.7开始工作。要在password_reset中启用对html格式的电子邮件的支持,我所要做的就是从email_template_name ='emails / password_reset_email_html.html更改重置功能中的电子邮件模板密钥名称
to
至
html_email_template_name='emails/password_reset_email_html.html',
html_email_template_name = '电子邮件/ password_reset_email_html.html',
thus the reset function would look as such:
因此重置功能看起来像这样:
def reset(request):
# Wrap the built-in password reset view and pass it the arguments
# like the template name, email template name, subject template name
# and the url to redirect after the password reset is initiated.
return password_reset(request, template_name='profile/reset.html',
html_email_template_name='emails/password_reset_email_html.html',
subject_template_name='emails/reset_subject.txt',
post_reset_redirect=reverse('success'))
#5
0
Based on Cem Kozinoglu solution I would suggest to change the form and overload send_mail instead of save method in the following way:
根据Cem Kozinoglu解决方案,我建议更改表单并以下列方式重载send_mail而不是save方法:
class CustomPasswordResetForm(PasswordResetForm):
def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
"""
Sends 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])
# New line introduce
email_message.attach_alternative(body, 'text/html')
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()
#6
0
You can use PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
您可以使用PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
Then you can override all the form options:
然后,您可以覆盖所有表单选项:
domain_override subject_template_name email_template_name use_https token_generator from_email request html_email_template_name extra_email_context
domain_override subject_template_name email_template_name use_https token_generator from_email request html_email_template_name extra_email_context
in my case i just override 2 props
在我的情况下,我只是覆盖2道具
class CustomPasswordResetSerializer(PasswordResetSerializer):
def get_email_options(self):
return {
'domain_override': 'anydomain.com',
'html_email_template_name': 'your_temp/password_reset_email.html',
}
#7
0
Here is the simple approach worked for me. Add our custom template path in such a way worked for me.
这是为我工作的简单方法。以这样的方式添加我们的自定义模板路径。
path('users/password/reset/', password_reset, {'html_email_template_name': 'registration/password_reset_email.html'},name='password_reset'),
path('users / password / reset /',password_reset,{'html_email_template_name':'registration / password_reset_email.html'},name ='password_reset'),
#8
0
After overwriting the PasswordResetForm and adding this line of code after email_message initialization I solve my problem:
在覆盖PasswordResetForm并在email_message初始化后添加这行代码后,我解决了我的问题:
email_message.attach_alternative(body, 'text/html')
#1
6
Here is how you can do the override:
urls.py
urls.py
url(r'^user/password/reset/$',
'YOUR_APP.views.password_reset',
{'post_reset_redirect' : '/#/login?resetemail=true'},
name="password_reset"),
views.py
views.py
from django.contrib.auth.views import password_reset as django_password_reset
from YOUR_APP.forms import CustomPasswordResetForm
def password_reset(*args, **kwargs):
"""
Overriding the Email Password Resert Forms Save to be able to send HTML email
"""
kwargs['password_reset_form'] = CustomPasswordResetForm
return django_password_reset(*args, **kwargs)
form.py
form.py
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator
class CustomPasswordResetForm(PasswordResetForm):
"""
Overriding the Email Password Resert Forms Save to be able to send HTML email
"""
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
use_https=False, token_generator=default_token_generator, request=None, email_subject_name='registration/password_reset_subject.txt', **kwargs):
from django.core.mail import EmailMultiAlternatives
from django.utils.html import strip_tags
from django.template.loader import render_to_string
from django.contrib.sites.models import get_current_site
from django.utils.http import int_to_base36
for user in self.users_cache:
if not domain_override:
current_site = get_current_site(request)
site_name = current_site.name
domain = current_site.domain
else:
site_name = domain = domain_override
c = {
'email': user.email,
'domain': domain,
'site_name': site_name,
'uid': int_to_base36(user.id),
'user': user,
'token': token_generator.make_token(user),
'protocol': use_https and 'https' or 'http',
}
render = render_to_string(email_template_name, c)
render_subject = render_to_string(email_subject_name, c)
msg = EmailMultiAlternatives(render_subject, strip_tags(render), None, [user.email])
msg.attach_alternative(render, "text/html")
msg.send()
#2
5
You can override save
method of django.contrib.auth.forms.PasswordResetForm
and pass new form as an argument to password_reset
view.
您可以覆盖django.contrib.auth.forms.PasswordResetForm的save方法,并将新表单作为参数传递给password_reset视图。
#3
0
After some amount of trial and error, I discovered a much, much more terse way to supply a custom templated password reset email in the latest version of Django (1.8).
经过一些试验和错误后,我发现了一种更简洁的方式来在最新版本的Django(1.8)中提供自定义模板化密码重置电子邮件。
In your project/urls.py
, add these imports:
在您的project / urls.py中,添加以下导入:
from django.contrib.auth import views as auth_views
from django.core.urlresolvers import reverse_lazy
And add the following route in your urlpatterns before the usual django contrib auth url route inclusion:
并在通常的django contrib auth url route包含之前在urlpatterns中添加以下路由:
url(r'^accounts/password/reset/$',
auth_views.password_reset,
{
'post_reset_redirect': reverse_lazy('auth_password_reset_done'),
'html_email_template_name': 'registration/password_reset_html_email.html'
},
name='auth_password_reset'),
url('^', include('django.contrib.auth.urls')),
And then, in your app's templates/registration
folder, create the password_reset_html_email.html
with whatever HTML template you want.
然后,在您的应用程序的模板/注册文件夹中,使用您想要的任何HTML模板创建password_reset_html_email.html。
The reason this seemed necessary lay in the source for django/contrib/auth/views.py
, which has the view function the original URL route is mapped to:
这似乎是必要的原因在于django / contrib / auth / views.py的源代码,它具有原始URL路由映射到的view函数:
147 def password_reset(request, is_admin_site=False,
148 template_name='registration/password_reset_form.html',
149 email_template_name='registration/password_reset_email.html',
150 subject_template_name='registration/password_reset_subject.txt',
151 password_reset_form=PasswordResetForm,
152 token_generator=default_token_generator,
153 post_reset_redirect=None,
154 from_email=None,
155 current_app=None,
156 extra_context=None,
157 html_email_template_name=None):
158
The html_email_template_name
is set to None
as default, and there didn't seem to be a way to assign its value, aside from rewriting this specific route for this case as I mentioned above.
默认情况下,html_email_template_name设置为None,除了为此情况重写此特定路由之外,似乎没有办法分配其值,如上所述。
Hopefully this helps without needing to copy-paste a bunch of nearly-identical code like some of the other answers suggested - feedback is welcome, of course!
希望这有助于无需复制粘贴一堆几乎完全相同的代码,如建议的其他一些答案 - 当然欢迎反馈!
#4
0
For me the research was time consuming but the solution rather trivial. No overrides no fiddling with forms or anything like that am using Django==1.8.6 but should work from at least django 1.7 onward. To enable support for html formatted emails in password_reset all I had to do is change the email template key name in reset function from email_template_name='emails/password_reset_email_html.html
对我来说,研究耗费时间,但解决方案相当微不足道。没有覆盖没有摆弄表格或类似的东西使用Django == 1.8.6,但至少应该从django 1.7开始工作。要在password_reset中启用对html格式的电子邮件的支持,我所要做的就是从email_template_name ='emails / password_reset_email_html.html更改重置功能中的电子邮件模板密钥名称
to
至
html_email_template_name='emails/password_reset_email_html.html',
html_email_template_name = '电子邮件/ password_reset_email_html.html',
thus the reset function would look as such:
因此重置功能看起来像这样:
def reset(request):
# Wrap the built-in password reset view and pass it the arguments
# like the template name, email template name, subject template name
# and the url to redirect after the password reset is initiated.
return password_reset(request, template_name='profile/reset.html',
html_email_template_name='emails/password_reset_email_html.html',
subject_template_name='emails/reset_subject.txt',
post_reset_redirect=reverse('success'))
#5
0
Based on Cem Kozinoglu solution I would suggest to change the form and overload send_mail instead of save method in the following way:
根据Cem Kozinoglu解决方案,我建议更改表单并以下列方式重载send_mail而不是save方法:
class CustomPasswordResetForm(PasswordResetForm):
def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
"""
Sends 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])
# New line introduce
email_message.attach_alternative(body, 'text/html')
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()
#6
0
You can use PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
您可以使用PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
Then you can override all the form options:
然后,您可以覆盖所有表单选项:
domain_override subject_template_name email_template_name use_https token_generator from_email request html_email_template_name extra_email_context
domain_override subject_template_name email_template_name use_https token_generator from_email request html_email_template_name extra_email_context
in my case i just override 2 props
在我的情况下,我只是覆盖2道具
class CustomPasswordResetSerializer(PasswordResetSerializer):
def get_email_options(self):
return {
'domain_override': 'anydomain.com',
'html_email_template_name': 'your_temp/password_reset_email.html',
}
#7
0
Here is the simple approach worked for me. Add our custom template path in such a way worked for me.
这是为我工作的简单方法。以这样的方式添加我们的自定义模板路径。
path('users/password/reset/', password_reset, {'html_email_template_name': 'registration/password_reset_email.html'},name='password_reset'),
path('users / password / reset /',password_reset,{'html_email_template_name':'registration / password_reset_email.html'},name ='password_reset'),
#8
0
After overwriting the PasswordResetForm and adding this line of code after email_message initialization I solve my problem:
在覆盖PasswordResetForm并在email_message初始化后添加这行代码后,我解决了我的问题:
email_message.attach_alternative(body, 'text/html')