#python #django
#python #django
Вопрос:
Мне кажется, django поддерживает только простые текстовые сообщения для электронных писем со сбросом пароля из коробки. Как я могу использовать шаблоны html для этой цели?
Ответ №1:
Вот как вы можете выполнить переопределение:
urls.py
url(r'^user/password/reset/
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
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()
Комментарии:
1. Я получаю эту ошибку: ошибка атрибута в объекте /user/password/reset/ 'CustomPasswordResetForm' не имеет атрибута 'users_cache'. Вы допустили ошибку? Должен ли я использовать какую-либо другую функцию вместо users_cache()? Что делают другие.
Ответ №2:
Вы можете переопределить save
метод django.contrib.auth.forms.PasswordResetForm
и передать новую форму в качестве аргумента для password_reset
просмотра.
Ответ №3:
Электронное письмо с сбросом пароля HTML с изображениями в Django 3.0
Обзор
- Создайте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Переопределение
django.contrib.auth.forms.PasswordResetForm
путем создания подкласса. - Переопределите аргументы для
PasswordResetForm.save()
, чтобы указать на ваши пользовательские шаблоны. - Переопределите
PasswordResetForm.send_email()
, если вы хотите вставлять изображения в HTML-сообщение электронной почты. - Установите
django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новыйPasswordResetForm
подкласс.
1. Создайте три шаблона
- В вашем каталоге шаблонов Django создайте подкаталог с именем "регистрация".
- В разделе "шаблоны / регистрация" добавьте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Шаблон электронной почты HTML должен быть хорошо структурированным HTML-документом. Смотрите пример ниже.
- Шаблон "* .txt" должен быть простым шаблоном (без HTML). Смотрите пример ниже.
Пример password_reset_email.html
{% autoescape off %}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Password Reset</title>
<style type="text/css">
body {
background-color: #ffffff;
font-size: 14px;
line-height: 16px;
font-family: PTSansRegular,Arial,Helvetica,sans-serif;
height: 100%;
margin: 0;
padding: 0;
border: 0;
outline: 0;
}
a.button {
background-color: #007bff;
border-color: #007bff;
border-radius: 5px;
color: #ffffff;
cursor: pointer;
display: inline-block;
font-size: 15px;
line-height: 18px;
font-weight: bold;
font-family: PTSansRegular,Arial,Helvetica,sans-serif;
padding: 7px;
text-align: center;
text-decoration: none;
white-space: nowrap;
width: 150px;
}
.center {
text-align: center
}
.container {
min-height: 100%;
min-width: 650px;
position: relative;
width: 100%;
}
p {
text-align:left
}
table {
margin: auto;
width:650px;
}
td {
padding-right: 14px;
padding-left: 14px;
}
</style>
</head>
<body>
<div class="container">
<!-- BEGIN EMAIL -->
<table align="center" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<p>Hello {{ user.get_username }},</p>
<p>A request has been received to change the password for your account.</p>
<p class="center">
<a target="_blank" class="button"
href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">
Reset Password
</a>
</p>
<p>This link can only be used once. If you need to reset your password again, please visit
<a href="{{ protocol }}://{{domain}}">{{ site_name }}</a> and request another reset.</p>
<p>If you did not make this request, please contact us immediately at
<a href="mailto: YOUR_SUPPORT_EMAIL">YOUR_SUPPORT_EMAIL</a>.</p>
<p>Sincerely,</p>
<p>The YOUR_COMPANY_NAME Team</p>
</td>
</tr>
</table>
<!-- END EMAIL -->
<table class="spacer">
<tr><td class="spacer">amp;nbsp;</td></tr>
</table>
<!-- BEGIN FOOTER -->
<table align="center">
<tr>
<td>
<p class="center"><img src="cid:logo" /></p>
</td>
</tr>
<tr>
<td class="center">YOUR_ADDRESS_AND_OR_COPYRIGHT</td>
</tr>
</table>
<!-- END FOOTER -->
</div>
</body>
</html>
{% endautoescape %}
Пример password_reset_email.txt
{% autoescape off %}
Hello {{ user.get_username }},
A request has been received to change the password for your account. Click the link below to reset your password.
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">
This link can only be used once. If you need to reset your password again, please visit
{{ protocol }}://{{domain}}">{{ site_name }} and request another reset.
If you did not make this request, please contact us immediately at YOUR_SUPPORT_EMAIL.
Sincerely,
The YOUR_COMPANY_NAME Team
YOUR_COMPANY_NAME
YOUR_ADDRESS_AND_OR_COPYRIGHT
{% endautoescape %}
2. Override django.contrib.auth.forms.PasswordResetForm
- In your Django app directory, create a module named "forms.py".
- Create a subclass of
django.contrib.auth.forms.PasswordResetForm
and override thesave()
method.
Example: forms.py
class CustomPasswordResetForm(PasswordResetForm):
"""Override the default Django password-reset form to send the password reset
email using both HTML and plain text.
"""
def save(
self,
domain_override: Optional[str] = None,
subject_template_name: str = PASSWORD_RESET_SUBJECT_TEMPLATE,
email_template_name: str = PASSWORD_RESET_TEXT_TEMPLATE,
use_https: Optional[bool] = None,
token_generator: PasswordResetTokenGenerator = default_token_generator,
from_email: Optional[str] = FROM_EMAIL,
request: Optional[WSGIRequest] = None,
html_email_template_name: Optional[str] = PASSWORD_RESET_HTML_TEMPLATE,
extra_email_context: Optional[Dict[str, str]] = None
) -> None:
"""Generate a one-use only link for resetting password and email it to
the user.
Args:
domain_override: Optional; Domain name to use in the email message
template that overrides the actual domain from which the email is
sent. Defaults to None.
subject_template_name: Optional; Warning: this argument is overridden
by the global variable ``PASSWORD_RESET_SUBJECT_TEMPLATE``.
email_template_name: Optional; Warning: this argument is overridden by
the global variable ``PASSWORD_RESET_TEXT_TEMPLATE``.
use_https: Optional; If True, use HTTPS, otherwise use HTTP. Defaults
to False. Note that if the password reset HTTP request is received
via HTTPS, `use_https` will be set to True by the auth view.
token_generator: Optional; Strategy object used to generate and check
tokens for the password reset mechanism. Defaults to an instance
of ``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
from_email: Optional; Warning: this argument is overridden by the
global variable``FROM_EMAIL``.
request: Optional; The HttpRequest object. Defaults to None.
html_email_template_name: Warning: this argument is overridden by the
global variable ``PASSWORD_RESET_HTML_TEMPLATE``.
extra_email_context: Optional; Key-value pairs to add to the context
dictionary used to render the password reset email templates.
Defaults to None.
"""
email_template_name = PASSWORD_RESET_TEXT_TEMPLATE
from_email = FROM_EMAIL
html_email_template_name = PASSWORD_RESET_HTML_TEMPLATE
subject_template_name = PASSWORD_RESET_SUBJECT_TEMPLATE
email = self.cleaned_data["email"]
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
UserModel = get_user_model()
email_field_name = UserModel.get_email_field_name() # type: ignore
for user in self.get_users(email):
user_email = getattr(user, email_field_name)
context = {
'email': user_email,
'domain': domain,
'site_name': site_name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': token_generator.make_token(user),
'protocol': 'https' if use_https else 'http',
**(extra_email_context or {}),
}
self.send_mail(
subject_template_name = subject_template_name,
email_template_name = email_template_name,
context = context,
from_email = from_email,
to_email = user_email,
html_email_template_name = html_email_template_name
)
3. Override the arguments for PasswordResetForm.save()
to point to your custom templates.
- In your "forms.py" module, add global variables as follows:
Example forms.py
from typing import Final
# Constants for sending password-reset emails.
LOGO_FILE_PATH: Final[str] = "img/logo.png"
LOGO_CID_NAME: Final[str] = "logo"
PASSWORD_RESET_FORM_TEMPLATE: Final[str] = "registration/password_reset_form.html"
PASSWORD_RESET_HTML_TEMPLATE: Final[str] = "registration/password_reset_email.html"
PASSWORD_RESET_TEXT_TEMPLATE: Final[str] = "registration/password_reset_email.txt"
PASSWORD_RESET_SUBJECT_TEMPLATE: Final[str] = "registration/password_reset_subject.txt"
SUPPORT_EMAIL: Final[str] = "YOUR_SUPPORT_EMAIL_ADDRESS"
FROM_EMAIL: Final[str] = f"YOUR_COMPANY_NAME Support <{SUPPORT_EMAIL}>"
4. Override PasswordResetForm.send_email()
if you want to embed images in the HTML email.
Example: forms.py
def get_as_mime_image(image_file_path: str, cid_name: str) -> MIMEImage:
"""Fetch an image file and return it wrapped in a ``MIMEImage`` object for use
in emails.
After the ``MIMEImage`` has been attached to an email, reference the image in
the HTML using the Content ID.
Example:
If the CID name is "logo", then the HTML reference would be:
<img src="cid:logo" />
Args:
image_file_path: The path of the image. The path must be findable by the
Django staticfiles app.
cid_name: The Content-ID name to use within the HTML email body to
reference the image.
Raises:
FileNotFoundError: If the image file cannot be found by the staticfiles app.
Returns:
MIMEImage: The image wrapped in a ``MIMEImage`` object and the Content ID
set to ``cid_name``.
"""
paths = finders.find(image_file_path)
if paths is None:
raise FileNotFoundError(f"{image_file_path} not found in static files")
if isinstance(paths, list):
final_path = paths[0]
else:
final_path = paths
with open(final_path, 'rb') as f:
image_data = f.read()
mime_image = MIMEImage(image_data)
mime_image.add_header("Content-ID", f"<{cid_name}>")
return mime_image
class CustomPasswordResetForm(PasswordResetForm):
"""Override the default Django password-reset form to send the password reset email using both HTML and plain text.
"""
def send_mail(
self,
subject_template_name: str,
email_template_name: str,
context: Dict[str, str],
from_email: Optional[str],
to_email: str,
html_email_template_name: Optional[str] = None,
) -> None:
"""Send a ``django.core.mail.EmailMultiAlternatives`` to ``to_email``.
This method also attaches the company logo, which can be added to the
email HTML template using:
<img src="cid:logo" />
Args:
subject_template_name: Path of the template to use as the email
subject.
email_template_name: Path of the template to use for the plain text
email body.
context: A context dictionary to use when rendering the password reset
email templates.
from_email: The From email address.
to_email: The To email address.
html_email_template_name: Optional; Path of the template to use for
the HTML email body. Defaults to None.
"""
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=from_email, to=[to_email],
reply_to=[from_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.mixed_subtype = "related"
mime_image = get_as_mime_image(image_file_path=LOGO_FILE_PATH, cid_name=LOGO_CID_NAME)
email_message.attach(mime_image) # type: ignore
email_message.send()
5. Установите django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новый PasswordResetForm
подкласс.
Django urls.py файл
from django.contrib.auth import views
from your_app.forms import CustomPasswordResetForm
views.PasswordResetView.form_class = CustomPasswordResetForm
urlpatterns = [
path('', home_view, name='home'),
path('accounts/', include('django.contrib.auth.urls')),
...
]
Завершить forms.py
"""Module that overrides the default Django password reset functionality by
sending emails containing both plain text as well as HTML along with the company logo.
"""
from email.mime.image import MIMEImage
from typing import Dict, Final, Optional
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator, PasswordResetTokenGenerator
from django.contrib.sites.shortcuts import get_current_site
from django.contrib.staticfiles import finders
from django.core.handlers.wsgi import WSGIRequest
from django.core.mail import EmailMultiAlternatives
from django.template import loader
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
# Constants for sending password-reset emails.
LOGO_FILE_PATH: Final[str] = "img/logo.png"
LOGO_CID_NAME: Final[str] = "logo"
PASSWORD_RESET_FORM_TEMPLATE: Final[str] = "registration/password_reset_form.html"
PASSWORD_RESET_HTML_TEMPLATE: Final[str] = "registration/password_reset_email.html"
PASSWORD_RESET_TEXT_TEMPLATE: Final[str] = "registration/password_reset_email.txt"
PASSWORD_RESET_SUBJECT_TEMPLATE: Final[str] = "registration/password_reset_subject.txt"
SUPPORT_EMAIL: Final[str] = "YOUR_SUPPORT_EMAIL_ADDRESS"
FROM_EMAIL: Final[str] = f"YOUR_COMPANY_NAME Support <{SUPPORT_EMAIL}>"
def get_as_mime_image(image_file_path: str, cid_name: str) -> MIMEImage:
"""Fetch an image file and return it wrapped in a ``MIMEImage`` object for use
in emails.
After the ``MIMEImage`` has been attached to an email, reference the image in
the HTML using the Content ID.
Example:
If the CID name is "logo", then the HTML reference would be:
<img src="cid:logo" />
Args:
image_file_path: The path of the image. The path must be findable by the
Django staticfiles app.
cid_name: The Content-ID name to use within the HTML email body to
reference the image.
Raises:
FileNotFoundError: If the image file cannot be found by the staticfiles app.
Returns:
MIMEImage: The image wrapped in a ``MIMEImage`` object and the Content ID
set to ``cid_name``.
"""
paths = finders.find(image_file_path)
if paths is None:
raise FileNotFoundError(f"{image_file_path} not found in static files")
if isinstance(paths, list):
final_path = paths[0]
else:
final_path = paths
with open(final_path, 'rb') as f:
image_data = f.read()
mime_image = MIMEImage(image_data)
mime_image.add_header("Content-ID", f"<{cid_name}>")
return mime_image
class CustomPasswordResetForm(PasswordResetForm):
"""Override the default Django password-reset form to send the password reset email using both HTML and plain text.
"""
def send_mail(
self,
subject_template_name: str,
email_template_name: str,
context: Dict[str, str],
from_email: Optional[str],
to_email: str,
html_email_template_name: Optional[str] = None,
) -> None:
"""Send a ``django.core.mail.EmailMultiAlternatives`` to ``to_email``.
This method also attaches the company logo, which can be added to the
email HTML template using:
<img src="cid:logo" />
Args:
subject_template_name: Path of the template to use as the email
subject.
email_template_name: Path of the template to use for the plain text
email body.
context: A context dictionary to use when rendering the password reset
email templates.
from_email: The From email address.
to_email: The To email address.
html_email_template_name: Optional; Path of the template to use for
the HTML email body. Defaults to None.
"""
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=from_email, to=[to_email],
reply_to=[from_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.mixed_subtype = "related"
mime_image = get_as_mime_image(image_file_path=LOGO_FILE_PATH, cid_name=LOGO_CID_NAME)
email_message.attach(mime_image) # type: ignore
email_message.send()
def save(
self,
domain_override: Optional[str] = None,
subject_template_name: str = PASSWORD_RESET_SUBJECT_TEMPLATE,
email_template_name: str = PASSWORD_RESET_TEXT_TEMPLATE,
use_https: Optional[bool] = None,
token_generator: PasswordResetTokenGenerator = default_token_generator,
from_email: Optional[str] = FROM_EMAIL,
request: Optional[WSGIRequest] = None,
html_email_template_name: Optional[str] = PASSWORD_RESET_HTML_TEMPLATE,
extra_email_context: Optional[Dict[str, str]] = None
) -> None:
"""Generate a one-use only link for resetting password and email it to
the user.
Args:
domain_override: Optional; Domain name to use in the email message
template that overrides the actual domain from which the email is
sent. Defaults to None.
subject_template_name: Optional; Warning: this argument is overridden
by the global variable ``PASSWORD_RESET_SUBJECT_TEMPLATE``.
email_template_name: Optional; Warning: this argument is overridden by
the global variable ``PASSWORD_RESET_TEXT_TEMPLATE``.
use_https: Optional; If True, use HTTPS, otherwise use HTTP. Defaults
to False. Note that if the password reset HTTP request is received
via HTTPS, `use_https` will be set to True by the auth view.
token_generator: Optional; Strategy object used to generate and check
tokens for the password reset mechanism. Defaults to an instance
of ``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
from_email: Optional; Warning: this argument is overridden by the
global variable``FROM_EMAIL``.
request: Optional; The HttpRequest object. Defaults to None.
html_email_template_name: Warning: this argument is overridden by the
global variable ``PASSWORD_RESET_HTML_TEMPLATE``.
extra_email_context: Optional; Key-value pairs to add to the context
dictionary used to render the password reset email templates.
Defaults to None.
"""
email_template_name = PASSWORD_RESET_TEXT_TEMPLATE
from_email = FROM_EMAIL
html_email_template_name = PASSWORD_RESET_HTML_TEMPLATE
subject_template_name = PASSWORD_RESET_SUBJECT_TEMPLATE
email = self.cleaned_data["email"]
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
UserModel = get_user_model()
email_field_name = UserModel.get_email_field_name() # type: ignore
for user in self.get_users(email):
user_email = getattr(user, email_field_name)
context = {
'email': user_email,
'domain': domain,
'site_name': site_name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': token_generator.make_token(user),
'protocol': 'https' if use_https else 'http',
**(extra_email_context or {}),
}
self.send_mail(
subject_template_name = subject_template_name,
email_template_name = email_template_name,
context = context,
from_email = from_email,
to_email = user_email,
html_email_template_name = html_email_template_name
)
Ответ №4:
Вы можете использовать PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
Затем вы можете переопределить все параметры формы:
domain_override subject_template_name email_template_name use_https token_generator from_email запрос html_email_template_name extra_email_context
в моем случае я просто переопределяю 2 реквизита
class CustomPasswordResetSerializer(PasswordResetSerializer):
def get_email_options(self):
return {
'domain_override': 'anydomain.com',
'html_email_template_name': 'your_temp/password_reset_email.html',
}
Ответ №5:
Вот простой подход, который сработал для меня. Добавление нашего пользовательского пути к шаблону таким образом сработало для меня.
path('users/password/reset/', password_reset, {'html_email_template_name': 'registration/password_reset_email.html'},name='password_reset'),
Ответ №6:
После некоторого количества проб и ошибок я обнаружил гораздо более краткий способ отправки пользовательского шаблонного электронного письма для сброса пароля в последней версии Django (1.8).
В вашем project/urls.py
добавьте эти импорта:
from django.contrib.auth import views as auth_views
from django.core.urlresolvers import reverse_lazy
И добавьте следующий маршрут в свои urlpatterns перед обычным включением в маршрут django contrib auth url:
url(r'^accounts/password/reset/
А затем в templates/registration
папке вашего приложения создайте password_reset_html_email.html
любой HTML-шаблон, который вы хотите.
Причина, по которой это казалось необходимым, заключалась в источнике, для django/contrib/auth/views.py
которого есть функция просмотра, к которой сопоставлен исходный маршрут URL:
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
Значение html_email_template_name
установлено None
по умолчанию, и, похоже, не было способа присвоить его значение, кроме перезаписи этого конкретного маршрута для этого случая, как я упоминал выше.
Надеюсь, это поможет без необходимости копировать-вставлять кучу почти идентичного кода, как некоторые другие предложенные ответы - обратная связь приветствуется, конечно!
Ответ №7:
Для меня исследование было трудоемким, но решение довольно тривиальным. Никаких переопределений, никаких манипуляций с формами или что-то в этом роде, я использую Django == 1.8.6, но должен работать как минимум с django 1.7 и далее. Чтобы включить поддержку электронных писем в формате html в password_reset, все, что мне нужно было сделать, это изменить имя ключа шаблона электронной почты в функции сброса с email_template_name='emails/password_reset_email_html.html
Для
html_email_template_name='emails/password_reset_email_html.html ',
таким образом, функция сброса будет выглядеть так:
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'))
Комментарии:
1. Где подходящее место в структуре проекта django для этого?
Ответ №8:
Основываясь на решении Джема Козиноглу, я бы предложил изменить форму и перегрузить send_mail вместо метода сохранения следующим образом:
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()
Ответ №9:
После перезаписи PasswordResetForm и добавления этой строки кода после инициализации email_message я решаю свою проблему:
email_message.attach_alternative(body, 'text/html')
,
'YOUR_APP.views.password_reset',
{'post_reset_redirect' : '/#/login?resetemail=true'},
name="password_reset"),
views.py
form.py
Комментарии:
1. Я получаю эту ошибку: ошибка атрибута в объекте /user/password/reset/ 'CustomPasswordResetForm' не имеет атрибута 'users_cache'. Вы допустили ошибку? Должен ли я использовать какую-либо другую функцию вместо users_cache()? Что делают другие.
Ответ №2:
Вы можете переопределить save
метод django.contrib.auth.forms.PasswordResetForm
и передать новую форму в качестве аргумента для password_reset
просмотра.
Ответ №3:
Электронное письмо с сбросом пароля HTML с изображениями в Django 3.0
Обзор
- Создайте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Переопределение
django.contrib.auth.forms.PasswordResetForm
путем создания подкласса. - Переопределите аргументы для
PasswordResetForm.save()
, чтобы указать на ваши пользовательские шаблоны. - Переопределите
PasswordResetForm.send_email()
, если вы хотите вставлять изображения в HTML-сообщение электронной почты. - Установите
django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новыйPasswordResetForm
подкласс.
1. Создайте три шаблона
- В вашем каталоге шаблонов Django создайте подкаталог с именем "регистрация".
- В разделе "шаблоны / регистрация" добавьте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Шаблон электронной почты HTML должен быть хорошо структурированным HTML-документом. Смотрите пример ниже.
- Шаблон "* .txt" должен быть простым шаблоном (без HTML). Смотрите пример ниже.
Пример password_reset_email.html
Пример password_reset_email.txt
2. Override django.contrib.auth.forms.PasswordResetForm
- In your Django app directory, create a module named "forms.py".
- Create a subclass of
django.contrib.auth.forms.PasswordResetForm
and override thesave()
method.
Example: forms.py
3. Override the arguments for PasswordResetForm.save()
to point to your custom templates.
- In your "forms.py" module, add global variables as follows:
Example forms.py
4. Override PasswordResetForm.send_email()
if you want to embed images in the HTML email.
Example: forms.py
5. Установите django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новый PasswordResetForm
подкласс.
Django urls.py файл
Завершить forms.py
Ответ №4:
Вы можете использовать PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
Затем вы можете переопределить все параметры формы:
domain_override subject_template_name email_template_name use_https token_generator from_email запрос html_email_template_name extra_email_context
в моем случае я просто переопределяю 2 реквизита
Ответ №5:
Вот простой подход, который сработал для меня. Добавление нашего пользовательского пути к шаблону таким образом сработало для меня.
path('users/password/reset/', password_reset, {'html_email_template_name': 'registration/password_reset_email.html'},name='password_reset'),
Ответ №6:
После некоторого количества проб и ошибок я обнаружил гораздо более краткий способ отправки пользовательского шаблонного электронного письма для сброса пароля в последней версии Django (1.8).
В вашем project/urls.py
добавьте эти импорта:
И добавьте следующий маршрут в свои urlpatterns перед обычным включением в маршрут django contrib auth url:
А затем в templates/registration
папке вашего приложения создайте password_reset_html_email.html
любой HTML-шаблон, который вы хотите.
Причина, по которой это казалось необходимым, заключалась в источнике, для django/contrib/auth/views.py
которого есть функция просмотра, к которой сопоставлен исходный маршрут URL:
Значение html_email_template_name
установлено None
по умолчанию, и, похоже, не было способа присвоить его значение, кроме перезаписи этого конкретного маршрута для этого случая, как я упоминал выше.
Надеюсь, это поможет без необходимости копировать-вставлять кучу почти идентичного кода, как некоторые другие предложенные ответы - обратная связь приветствуется, конечно!
Ответ №7:
Для меня исследование было трудоемким, но решение довольно тривиальным. Никаких переопределений, никаких манипуляций с формами или что-то в этом роде, я использую Django == 1.8.6, но должен работать как минимум с django 1.7 и далее. Чтобы включить поддержку электронных писем в формате html в password_reset, все, что мне нужно было сделать, это изменить имя ключа шаблона электронной почты в функции сброса с email_template_name='emails/password_reset_email_html.html
Для
html_email_template_name='emails/password_reset_email_html.html ',
таким образом, функция сброса будет выглядеть так:
Комментарии:
1. Где подходящее место в структуре проекта django для этого?
Ответ №8:
Основываясь на решении Джема Козиноглу, я бы предложил изменить форму и перегрузить send_mail вместо метода сохранения следующим образом:
Ответ №9:
После перезаписи PasswordResetForm и добавления этой строки кода после инициализации email_message я решаю свою проблему:
,
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')),
А затем в templates/registration
папке вашего приложения создайте password_reset_html_email.html
любой HTML-шаблон, который вы хотите.
Причина, по которой это казалось необходимым, заключалась в источнике, для django/contrib/auth/views.py
которого есть функция просмотра, к которой сопоставлен исходный маршрут URL:
Значение html_email_template_name
установлено None
по умолчанию, и, похоже, не было способа присвоить его значение, кроме перезаписи этого конкретного маршрута для этого случая, как я упоминал выше.
Надеюсь, это поможет без необходимости копировать-вставлять кучу почти идентичного кода, как некоторые другие предложенные ответы — обратная связь приветствуется, конечно!
Ответ №7:
Для меня исследование было трудоемким, но решение довольно тривиальным. Никаких переопределений, никаких манипуляций с формами или что-то в этом роде, я использую Django == 1.8.6, но должен работать как минимум с django 1.7 и далее. Чтобы включить поддержку электронных писем в формате html в password_reset, все, что мне нужно было сделать, это изменить имя ключа шаблона электронной почты в функции сброса с email_template_name=’emails/password_reset_email_html.html
Для
html_email_template_name=’emails/password_reset_email_html.html ‘,
таким образом, функция сброса будет выглядеть так:
Комментарии:
1. Где подходящее место в структуре проекта django для этого?
Ответ №8:
Основываясь на решении Джема Козиноглу, я бы предложил изменить форму и перегрузить send_mail вместо метода сохранения следующим образом:
Ответ №9:
После перезаписи PasswordResetForm и добавления этой строки кода после инициализации email_message я решаю свою проблему:
,
‘YOUR_APP.views.password_reset’,
{‘post_reset_redirect’ : ‘/#/login?resetemail=true’},
name=«password_reset»),views.py
form.py
Комментарии:
1. Я получаю эту ошибку: ошибка атрибута в объекте /user/password/reset/ ‘CustomPasswordResetForm’ не имеет атрибута ‘users_cache’. Вы допустили ошибку? Должен ли я использовать какую-либо другую функцию вместо users_cache()? Что делают другие.
Ответ №2:
Вы можете переопределить save
метод django.contrib.auth.forms.PasswordResetForm
и передать новую форму в качестве аргумента для password_reset
просмотра.
Ответ №3:
Электронное письмо с сбросом пароля HTML с изображениями в Django 3.0
Обзор
- Создайте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Переопределение
django.contrib.auth.forms.PasswordResetForm
путем создания подкласса. - Переопределите аргументы для
PasswordResetForm.save()
, чтобы указать на ваши пользовательские шаблоны. - Переопределите
PasswordResetForm.send_email()
, если вы хотите вставлять изображения в HTML-сообщение электронной почты. - Установите
django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новыйPasswordResetForm
подкласс.
1. Создайте три шаблона
- В вашем каталоге шаблонов Django создайте подкаталог с именем «регистрация».
- В разделе «шаблоны / регистрация» добавьте три шаблона:
password_reset_email.html
password_reset_email.txt
password_reset_subject.txt
- Шаблон электронной почты HTML должен быть хорошо структурированным HTML-документом. Смотрите пример ниже.
- Шаблон «* .txt» должен быть простым шаблоном (без HTML). Смотрите пример ниже.
Пример password_reset_email.html
Пример password_reset_email.txt
2. Override django.contrib.auth.forms.PasswordResetForm
- In your Django app directory, create a module named «forms.py».
- Create a subclass of
django.contrib.auth.forms.PasswordResetForm
and override thesave()
method.
Example: forms.py
3. Override the arguments for PasswordResetForm.save()
to point to your custom templates.
- In your «forms.py» module, add global variables as follows:
Example forms.py
4. Override PasswordResetForm.send_email()
if you want to embed images in the HTML email.
Example: forms.py
5. Установите django.contrib.auth.views.PasswordResetView.form_class
для использования ваш новый PasswordResetForm
подкласс.
Django urls.py файл
Завершить forms.py
Ответ №4:
Вы можете использовать PasswordResetSerializer http://django-rest-auth.readthedocs.io/en/latest/configuration.html
Затем вы можете переопределить все параметры формы:
domain_override subject_template_name email_template_name use_https token_generator from_email запрос html_email_template_name extra_email_context
в моем случае я просто переопределяю 2 реквизита
Ответ №5:
Вот простой подход, который сработал для меня. Добавление нашего пользовательского пути к шаблону таким образом сработало для меня.
path('users/password/reset/', password_reset, {'html_email_template_name': 'registration/password_reset_email.html'},name='password_reset'),
Ответ №6:
После некоторого количества проб и ошибок я обнаружил гораздо более краткий способ отправки пользовательского шаблонного электронного письма для сброса пароля в последней версии Django (1.8).
В вашем project/urls.py
добавьте эти импорта:
И добавьте следующий маршрут в свои urlpatterns перед обычным включением в маршрут django contrib auth url:
А затем в templates/registration
папке вашего приложения создайте password_reset_html_email.html
любой HTML-шаблон, который вы хотите.
Причина, по которой это казалось необходимым, заключалась в источнике, для django/contrib/auth/views.py
которого есть функция просмотра, к которой сопоставлен исходный маршрут URL:
Значение html_email_template_name
установлено None
по умолчанию, и, похоже, не было способа присвоить его значение, кроме перезаписи этого конкретного маршрута для этого случая, как я упоминал выше.
Надеюсь, это поможет без необходимости копировать-вставлять кучу почти идентичного кода, как некоторые другие предложенные ответы — обратная связь приветствуется, конечно!
Ответ №7:
Для меня исследование было трудоемким, но решение довольно тривиальным. Никаких переопределений, никаких манипуляций с формами или что-то в этом роде, я использую Django == 1.8.6, но должен работать как минимум с django 1.7 и далее. Чтобы включить поддержку электронных писем в формате html в password_reset, все, что мне нужно было сделать, это изменить имя ключа шаблона электронной почты в функции сброса с email_template_name=’emails/password_reset_email_html.html
Для
html_email_template_name=’emails/password_reset_email_html.html ‘,
таким образом, функция сброса будет выглядеть так:
Комментарии:
1. Где подходящее место в структуре проекта django для этого?
Ответ №8:
Основываясь на решении Джема Козиноглу, я бы предложил изменить форму и перегрузить send_mail вместо метода сохранения следующим образом:
Ответ №9:
После перезаписи PasswordResetForm и добавления этой строки кода после инициализации email_message я решаю свою проблему: