Object of type User is not JSON serializable

Я пытаюсь переопределить форму PasswordResetForm так, чтобы после метода save() письмо отправлялось таской celery асинхронно, но к сожалению возникает ошибка. Вот трейс:

  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/contrib/auth/views.py", line 222, in dispatch
    return super().dispatch(*args, **kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/views/generic/edit.py", line 142, in post
    return self.form_valid(form)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/lib/python3.8/site-packages/django/contrib/auth/views.py", line 235, in form_valid
    form.save(**opts)
  File "/mnt/c/users/huawei/desktop/adsboard_project_venv/tbads/reset_password_system/forms.py", line 52, in save
    json.dumps(context), json.dumps(from_email), json.dumps(user.email),
  File "/usr/lib/python3.8/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type User is not JSON serializable

Мой код:

forms.py

from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
from django.contrib.auth import get_user_model
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from .tasks import send_mail_message


class GetUserEmailForm(PasswordResetForm):
    email = forms.EmailField(
        widget=forms.EmailInput(attrs={'class': 'input-login input-form', 'placeholder': 'Email'})
    )

    def clean_email(self):
        email = self.cleaned_data.get('email')
        try:
            get_user_model().objects.get(email=email)
        except get_user_model().DoesNotExist:
            raise forms.ValidationError(
                'Пользователь с таким адресом электронной почты не существует.'
            )
        return email

    def save(self, domain_override=None,
             subject_template_name='registration/password_reset_subject.txt',
             email_template_name='registration/password_reset_email.html',
             use_https=False, token_generator=default_token_generator,
             from_email=None, request=None, html_email_template_name=None, **kwargs):
        email = self.cleaned_data["email"]
        for user in self.get_users(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
            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',
            }

            send_mail_message.delay(subject_template_name, email_template_name,
                                    context, from_email, user.email,
                                    html_email_template_name=html_email_template_name)

tasks.py

from django.template import loader
from tbads.celery import celery_app
from django.core.mail import EmailMultiAlternatives


@celery_app.task
def send_mail_message(subject_template_name, email_template_name,
                      context, from_email, to_email, html_email_template_name=None):
    subject = loader.render_to_string(subject_template_name, context)
    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()

Я пытался преобразовать аргументы путем использования json.dumps и to.JSON но результатов это принесло мало, подскажите, пожалуйста, в чем же проблема?


Ответы (1 шт):

Автор решения: 5c0rp

Ваша ошибка связана с тем что объект User не может быть преобразован в данные подходящие для json. Как вариант то можете убрать 'user': user из context. Если объект user ваш необходим а дальнейшем то замените его сразу на нужные поля - как пример first_name: user.first_name и добавьте их в ваш context.

→ Ссылка