Object of type 'xxx' is not JSON serializable Django UpdateView

I am trying to edit with UpdateView a form after I have entered and saved the information. I send the parameters with AJAX from the view, however I get the error: "Object of type Form is not JSON serializable".

Attached are some related code snippets.

models.py

class Formulario(models.Model):
   creado_el = models.DateTimeField(_('creado el'), null=False, blank=True, default=tz.now)
   fecha_ingreso = models.DateTimeField(auto_now_add=True, null=True, blank=True)
   monto = models.CharField(_('monto'), null=False, blank=False, max_length=40)
   plazo_meses = models.CharField(_('plazo meses'), null=False, blank=False, max_length=40)
   nombre_1 = models.CharField(_('nombre 1'), max_length=40, null=False, blank=False)
   nombre_2 = models.CharField(_('nombre 2'), max_length=40, null=True, blank=True)  # Puede 
   estar en blanco
   apellido_1 = models.CharField(_('apellido 1'), max_length=40, null=False, blank=False)
   apellido_2 = models.CharField(_('apellido 2'), max_length=40, null=True, blank=True)
   tipo_doc = models.ForeignKey(TipoDocumento, on_delete=models.SET_NULL, null=True)
   dni = models.CharField(_('dni'), max_length=20, null=False, blank=False)
   f_nacimiento = models.DateField(_('f_nacimiento'), null=False, blank=False)
   email_1 = models.EmailField(_('email 1'), max_length=254, null=False, blank=False)
   celular = models.IntegerField(_('celular'), null=False, blank=False)
   e_civil = models.ForeignKey(EstadoCivil, on_delete=models.SET_NULL, null=True)
   genero = models.ForeignKey(Genero, on_delete=models.SET_NULL, null=True)
   dependientes = models.ForeignKey(Dependientes, on_delete=models.SET_NULL, null=True)
   tipo_ingreso = models.ForeignKey(TipoIngreso, on_delete=models.SET_NULL, null=True)
   salario = models.DecimalField(_('salario'), max_digits=6, decimal_places=2, null=False, 
   blank=False)
   empresa_1 = models.CharField(_('empresa'), max_length=50)
   in_extras = models.ForeignKey(IngresosExtra, on_delete=models.SET_NULL, null=True)
   estudios = models.ForeignKey(Escolaridad, on_delete=models.SET_NULL, null=True)
   p_expuesto = models.ForeignKey(PEP, on_delete=models.SET_NULL, null=True)
   # ciudad = models.CharField(_('ciudad'), max_length=40, null=False, blank=False)  # Lugar 
   de residencia, dirección
   # sector = models.CharField(_('sector'), max_length=40, null=False, blank=False)
   provincia = models.ForeignKey(Provincia, on_delete=models.SET_NULL, null=True)
   distrito = models.ForeignKey(Distrito, on_delete=models.SET_NULL, null=True)
   corregimiento = models.ForeignKey(Corregimiento, on_delete=models.SET_NULL, null=True)
   direccion = models.CharField(_('dir_cliente'), max_length=250, null=True, blank=True, 
   default='')
   ref = models.CharField(_('ref'), max_length=100, null=True, blank=True)  # opcional
   terms = models.BooleanField(_('terms'), default=False)
   apc = models.BooleanField(_('apc'), default=False)
   check_1 = models.BooleanField(_('check 1'), default=False, null=True, blank=True)
   check_2 = models.BooleanField(_('check 2'), default=False, null=True, blank=True)

   def __str__(self):
       return self.nombre_1

   def toJSON(self):
       item = model_to_dict(self)
       return item

   class Meta:
       verbose_name = 'Formulario'
       verbose_name_plural = 'Formularios'
       ordering = ['id']

forms.py

class EditSolicitud(ModelForm):
  provincia = ModelChoiceField(queryset=Provincia.objects.all(), widget=Select(attrs={
      'class': 'form-select form-control',
  }))

  distrito = ModelChoiceField(queryset=Distrito.objects.all(), widget=Select(attrs={
      'class': 'form-select form-control',
  }))

  corregimiento = ModelChoiceField(queryset=Corregimiento.objects.all(), widget=Select(attrs={
      'class': 'form-select form-control',
  }))

  class Meta:
    model = Formulario
    fields = '__all__'

    widgets = {
        'nombre_1': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese nombre',
                'autocomplete': 'off',
            }
        ),
        'nombre_2': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese nombre',
                'autocomplete': 'off'
            }
        ),
        'apellido_1': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese apellido',
                'autocomplete': 'off'
            }
        ),
        'apellido_2': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese apellido',
                'autocomplete': 'off'
            }
        ),
        'tipo_doc': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'dni': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese ID',
                'autocomplete': 'off'
            }
        ),
        'f_nacimiento': DateInput(format='%Y-%m-%d', attrs={
            'class': 'form-control datepicker',
            'id': 'datepicker',
            # 'placeholder': x,
            # 'value': x,
            # 'data-target': '#f_nacimiento'
        }
                                  ),
        'email_1': EmailInput(
            attrs={
                'class': 'form-control',
                'placeholder': '[email protected]',
                'autocomplete': 'on'
            }
        ),
        'celular': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': '61234567',
                'autocomplete': 'off'
            }
        ),
        'e_civil': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'genero': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'dependientes': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'tipo_ingreso': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'salario': NumberInput(
            attrs={
                'class': 'form-control',
                'autocomplete': 'off',
                'min': '100',
                'placeholder': '100.00'
            }
        ),
        'empresa_1': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Ingrese nombre',
                'autocomplete': 'off'
            }
        ),
        'in_extras': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'estudios': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'p_expuesto': Select(
            attrs={
                'class': 'form-select form-control',
                'autocomplete': 'off'
            }
        ),
        'direccion': TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': 'Panamá',
                'autocomplete': 'off'
            }
        ),

        'ref': TextInput(
            attrs={
                'class': 'form-control',
                'autocomplete': 'off'
            }
        ),
        'terms': CheckboxInput(
            attrs={
                'type': 'checkbox',
                'class': 'custom-control-input',
                'required': 'True',
                # 'disabled': None,
                'checked': None,
                # 'required': 'True'
            }
        ),
        'apc': CheckboxInput(
            attrs={
                'type': 'checkbox',
                'class': 'custom-control-input',
                'required': 'True',
                # 'disabled': None,
                'checked': None,
                # 'required': 'True'
            }
        ),
        'monto': NumberInput(
            attrs={
                # 'type': 'range',
                'class': 'form-control',
                # 'required': 'True',
                'min': '300',
                'max': '3500',
                # 'step': '10',
                'id': 'entrada_1',
                'oninput': 'myFunction()',
                'value': '1000'
            }
        ),
        'plazo_meses': NumberInput(
            attrs={
                # 'type': 'range',
                'class': 'form-control',
                # 'required': 'True',
                'min': '6',
                'max': '24',
                # 'step': '1',
                'id': 'entrada_2',
                'oninput': 'myFunction()',
                'value': '24'
            }
        ),
        'check_1': CheckboxInput(
            attrs={
                'type': 'checkbox',
                'class': 'custom-control-input',
            }
        ),
        'check_2': CheckboxInput(
            attrs={
                'type': 'checkbox',
                'class': 'custom-control-input',
            }
        ),
    }

views.py

class EdicionSolicitud(UpdateView):
  # print([e.check for e in Formulario.objects.filter(pk=1)])
  model = Formulario
  form_class = EditSolicitud
  template_name = 'ventas/nuevas/1_solicitudes_rev.html'
  success_url = reverse_lazy('ventas:solicitudes_nuevas')

  def dispatch(self, request, *args, **kwargs):
      self.object = self.get_object()
      return super().dispatch(request, *args, **kwargs)

  def post(self, request, *args, **kwargs):
      data = {}
      try:
          action = request.POST['action']
          if action == 'edit':
              # form = CategoryForm(request.POST)
              form = self.get_form()
              data = form.save()
          elif action == 'select_p':
              data = []
              for i in Distrito.objects.filter(provincia_id=request.POST['id']):
                  data.append({'id': i.id, 'name': i.nombre})
          elif action == 'select_d':
              data = []
              for i in Corregimiento.objects.filter(distrito_id=request.POST['id']):
                  data.append({'id': i.id, 'name': i.nombre})
          else:
              data['error'] = 'No ha ingresado ninguna opción'
      except Exception as e:
          data['error'] = str(e)
      return JsonResponse(data, safe=False)

  def get_context_data(self, **kwargs):
      context = super().get_context_data(**kwargs)
      # context['form'] = SolicitudRevisada()
      context['section_name'] = 'Ventas'
      context['card_title_1'] = 'Editar solicitud'
      context['active_ventas'] = 'active'
      context['active_ventas_nuevas'] = 'active'
      context['retorno_1'] = 'ventas:solicitudes_nuevas'
      return context

Javascript AJAX

  $('#form_edit').on('submit', function (e) {
        e.preventDefault();
        var parameters = $(this).serializeArray();
        console.log(parameters);
        $.ajax({
            url: window.location.pathname,
            type: 'POST',
            data: parameters,
            dataType: 'json'
        }).done(function (data) {
            console.log(data);
            if (!data.hasOwnProperty('error')) {
                location.href = '{{ retorno_1 }}';
                return false;
            }
            message_error(data.error);
        }).fail(function (jqXHR, textStatus, errorThrown) {
            alert(textStatus + ': ' + errorThrown);
        }).always(function (data) {
            console.log(data);
        });
    });

AJAX select part1

$(function () {
$('select[name="provincia"]').on('change', function () {
    var id = $(this).val();
    var select_distrito = $('select[name="distrito"]');
    var select_corregimiento = $('select[name="corregimiento"]');
    var options = '<option value="">---------------</option>';
    select_corregimiento.html(options);
    if (id === '') {
        select_distrito.html(options);
        return false;
    }
    $.ajax({
        url: window.location.pathname, //window.location.pathname
        type: 'POST',
        data: {
            'action': 'select_p',
            'id': id
        },
        dataType: 'json',
    }).done(function (data) {
        console.log(data);
        if (!data.hasOwnProperty('error')) {
            $.each(data, function (key, value) {
                options += '<option value="' + value.id + '">' + value.name + '</option>'
            })
            return false;
        }
        message_error(data.error);
    }).fail(function (jqXHR, textStatus, errorThrown) {
        alert(textStatus + ': ' + errorThrown);
    }).always(function (data) {
        select_distrito.html(options);
    });
  })
 });

AJAX select part2

$(function () {
$('select[name="distrito"]').on('change', function () {
    var id = $(this).val();
    var select_corregimiento = $('select[name="corregimiento"]');
    var options = '<option value="">---------------</option>';
    if (id === '') {
        select_corregimiento.html(options);
        return false;
    }
    $.ajax({
        url: window.location.pathname, //window.location.pathname
        type: 'POST',
        data: {
            'action': 'select_d',
            'id': id
        },
        dataType: 'json',
    }).done(function (data) {
        console.log(data);
        if (!data.hasOwnProperty('error')) {
            $.each(data, function (key, value) {
                options += '<option value="' + value.id + '">' + value.name + '</option>'
            })
            return false;
        }
        message_error(data.error);
    }).fail(function (jqXHR, textStatus, errorThrown) {
        alert(textStatus + ': ' + errorThrown);
    }).always(function (data) {
        select_corregimiento.html(options);
    });
  })
});

Upvotes: 1

Views: 1834

Answers (1)

marcelob33
marcelob33

Reputation: 66

In the post method of your UpdateView, you're trying to return a JsonResponse

return JsonResponse(data, safe=False)

But if you look at your code, data is a Form object when the action is 'edit'.

if action == 'edit':
    # form = CategoryForm(request.POST)
    form = self.get_form()
    data = form.save()

You need to serialize that form before trying to send it as a JSonResponse just like you did for the other actions. The variable "data" has to be a dictionary.

https://docs.djangoproject.com/en/3.2/ref/request-response/#jsonresponse-objects

Upvotes: 1

Related Questions