Login form that contains only the Users email field.
| 93 | |
| 94 | |
| 95 | class EmailLoginForm(BaseLoginForm): |
| 96 | """Login form that contains only the Users email field.""" |
| 97 | |
| 98 | subject_template_name = "registration/login_subject.txt" |
| 99 | email_template_name = "registration/login_email.txt" |
| 100 | html_email_template_name = "registration/login_email.html" |
| 101 | from_email = None |
| 102 | field_name = None |
| 103 | |
| 104 | def __init__(self, request, *args, **kwargs): |
| 105 | self.request = request |
| 106 | super().__init__(*args, **kwargs) |
| 107 | |
| 108 | self.field_name = self.field_name or get_user_model().get_email_field_name() |
| 109 | model_field = get_user_model()._meta.get_field(self.field_name) |
| 110 | field = model_field.formfield() |
| 111 | field.required = True |
| 112 | |
| 113 | self.fields[self.field_name] = field |
| 114 | |
| 115 | def get_users(self, email=None): |
| 116 | if connection.vendor == "postgresql": |
| 117 | query = {self.field_name: email} |
| 118 | else: |
| 119 | query = {f"{self.field_name}__iexact": email} |
| 120 | return get_user_model()._default_manager.filter(**query).iterator() |
| 121 | |
| 122 | def save(self): |
| 123 | """ |
| 124 | Generate and send a one-time link for the user to login. |
| 125 | |
| 126 | This method will be called from the view and passed the views request. |
| 127 | """ |
| 128 | email = self.cleaned_data[self.field_name] |
| 129 | for user in self.get_users(email): |
| 130 | context = self.get_mail_context(self.request, user) |
| 131 | self.send_mail(email, context) |
| 132 | |
| 133 | def send_mail(self, to_email, context): |
| 134 | """Send a django.core.mail.EmailMultiAlternatives to `to_email`.""" |
| 135 | subject = loader.render_to_string(self.subject_template_name, context) |
| 136 | # Email subject *must not* contain newlines |
| 137 | subject = "".join(subject.splitlines()) |
| 138 | body = loader.render_to_string(self.email_template_name, context) |
| 139 | |
| 140 | email_message = EmailMultiAlternatives( |
| 141 | subject, body, self.from_email, [to_email] |
| 142 | ) |
| 143 | try: |
| 144 | template = loader.get_template(self.html_email_template_name) |
| 145 | except TemplateDoesNotExist: |
| 146 | pass |
| 147 | else: |
| 148 | html_email = template.render(context, self.request) |
| 149 | email_message.attach_alternative(html_email, "text/html") |
| 150 | |
| 151 | email_message.send() |
no outgoing calls