save() method provided by Django dont work with TextChoices

I got a model in my app that use an ArrayField (‘caracteristicas’) where its base model its a CharField with choices from a different TextChoices class. When I try to save the generated object, its launch an error with no “exception message” in the Django webpage. If I try to do it in the DjangoAdmin Its comes to a stack overflow of recursion.
There is no problem in the form that I use to create the object nor the method (‘Exception as e’ and ‘form_class.errors’ are both empty)
I tried to create an object of “Espacio” without this ArrayField (simply various boolean fields with True if it got the characteristic and False in the other case)…and it works! I dont know whats happening
Code below

Model “Espacio”

from django.db import models
from django.contrib.postgres.fields import ArrayField
from usuarios.models import User
from base.models import EstadoEspacio, Caracteristicas, TiposEspacios

Create your models here.

Modelo asociado a los espacios

class Espacio(models.Model):
# Título del espacio
titulo = models.CharField(max_length=100)

# Descripción del espacio
descripcion = models.TextField()

# Imágenes del espacio
image1 = models.ImageField(upload_to='base/Images/EspaciosImages')
image2 = models.ImageField(upload_to='base/Images/EspaciosImages')
image3 = models.ImageField(upload_to='base/Images/EspaciosImages')

# Tipo de combo
opcionesTiposEspacio = [(choice.value, choice.label) for choice in TiposEspacios]
tipoEspacio = models.CharField(choices=opcionesTiposEspacio, max_length= 2, default=TiposEspacios.otros)

# Superficie del espacio
superficie = models.IntegerField()

def caracteristicaDefault():
    return Caracteristicas.baño

# Características del espacio
#opcionesCaracteristicas = [(choice.value, choice.label) for choice in Caracteristicas]
caracteristicas = ArrayField(base_field=models.CharField(max_length=100))

# Dirección del espacio
direccion = models.CharField(max_length=150)

# Fecha de creación del espacio
created = models.DateTimeField(auto_now_add = True)

opcionesEstados = [(choice.value, choice.label) for choice in EstadoEspacio]
estado = models.CharField(max_length=2, choices=opcionesEstados, default=EstadoEspacio.publicado)

 # Relación con el usuario propietario del espacio
user = models.ForeignKey(User, on_delete=models.CASCADE)

def __str__(self):
    return self.titulo

View “nuevoEspacio”

def nuevoEspacio(request):
opcionesCaracteristicas = [(choice.value, choice.label) for choice in Caracteristicas]
if request.method == ‘POST’:
print(request.POST)
# Crear una instancia del formulario con los datos de la solicitud
form_class = espacioForm(request.POST, request.FILES)

      if form_class.is_valid():
           try:
                # Guardar el espacio en la base de datos, asociándolo al usuario actual
                espacio = form_class.save(commit=False)
                espacio.user = request.user

                caracteristicasSeleccionadas = []

                for i,j in enumerate(opcionesCaracteristicas):
                     field_name = f"caracteristicas_{i}"
                     if request.POST.get(field_name):
                          caracteristicasSeleccionadas.append(request.POST.get(field_name))
                
                espacio.caracteristicas = ", ".join(caracteristicasSeleccionadas)
                print(form_class.errors)
                espacio.save()
                # Mostrar mensaje de éxito y redirigir a la página principal
                messages.success(request, 'Espacio creado correctamente', 'success')
                return redirect('/')
           except Exception as e:
                messages.error(request, f'No se pudo crear el espacio:{str(e)}', 'danger')
                return redirect('nuevoEspacio')
 else:
    # Crear una instancia vacía del formulario
    form_class = espacioForm()

 contexto ={
      'form': form_class,
      'caracteristicas': opcionesCaracteristicas,
 }
 messages.error(request, form_class.errors, 'danger')

Form “espacioForm”

class espacioForm(forms.ModelForm):
opcionesCaracteristicas = forms.MultipleChoiceField(choices=[(choice.value, choice.label) for choice in Caracteristicas], widget= forms.CheckboxSelectMultiple(attrs={‘class’: ‘custom-control-input’}), required=False)
caracteristicas = forms.CharField(widget=forms.HiddenInput(), required=False)

class Meta:
model = Espacio

  # Campos excluidos del formulario
  exclude = ('user', 'estado')

  # Todos los campos del modelo se incluyen en el formulario
  fields = "__all__"

  # Configuración de widgets para los campos del formulario
  widgets = {
     'titulo': forms.TextInput(attrs={'class': 'form-control', }),
     'descripcion': forms.Textarea(attrs={'class': 'form-control', 'style':'height: 100px'}),
     'image1': forms.FileInput(attrs={'class': 'form-control form-control-sm my-3', 'type':'file'}),
     'image2': forms.FileInput(attrs={'class': 'form-control form-control-sm my-3', 'type':'file'}),
     'image3': forms.FileInput(attrs={'class': 'form-control form-control-sm my-3', 'type':'file'}),
     'tipoEspacio': forms.Select(attrs={'class': 'custom-select'}),
     'superficie' : forms.NumberInput(attrs={'class': 'form-control'}),
     'direccion': forms.TextInput(attrs={'class': 'form-control', }),
  }

Template (only the fragment where I capture the characteristic

{% for value, label in caracteristicas %}
{{ label }}
{% endfor %}

I was manually debugging the view and discover that the problem its in the line “espacio.save()”, all the other lines works properly
If someone can bend me a hand, I will be eternally grateful

Side note: When posting code here, enclose the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```. This forces the forum software to keep your code properly formatted.

You have:

But, you’re setting that field to a string value, not a list. From what I’m seeing in the code, you need to change:

to:
espacio.caracteristicas = caracteristicasSeleccionadas

Hi Ken, thanks for the tip about the “”"!! And thanks for the reply
You got right, I was making a bad assignment, but the error continues after that correction

Please post the complete traceback you’re getting.

Okey, its something big. Near the end the error changes and talk about another exception, but its stuck in a code line with recursion

Environment:

Request Method: POST
Request URL: http://localhost:8000/admin/espacios/espacio/add/

Django Version: 4.1.7
Python Version: 3.11.3
Installed Applications:
[‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘base.apps.BaseConfig’,
‘usuarios’,
‘espacios’,
‘reserva’]
Installed Middleware:
[‘django.middleware.security.SecurityMiddleware’,
‘django.contrib.sessions.middleware.SessionMiddleware’,
‘django.middleware.common.CommonMiddleware’,
‘django.middleware.csrf.CsrfViewMiddleware’,
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
‘django.contrib.messages.middleware.MessageMiddleware’,
‘django.middleware.clickjacking.XFrameOptionsMiddleware’]

Traceback (most recent call last):
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\query.py”, line 808, in iter
yield from iter(self._query)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\query.py”, line 167, in iter
yield self._align_results(doc)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\query.py”, line 269, in _align_results
if selected.table == self.left_table:

Here is where the recursion starts, in line 133

File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\sql_tokens.py”, line 133, in table
return alias2token[name].table
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\sql_tokens.py”, line 133, in table
return alias2token[name].table
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\sql_tokens.py”, line 133, in table
return alias2token[name].table

And here its ends

File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\sql_tokens.py”, line 130, in table
name = self.given_table
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\sql_tokens.py”, line 141, in given_table
name = self._token.get_real_name()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 361, in get_real_name
return self._get_first_name(dot_idx)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 386, in _get_first_name
return token.get_name()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 355, in get_name
return self.get_alias() or self.get_real_name()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 344, in get_alias
_, ws = self.token_next_by(t=T.Whitespace)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 244, in token_next_by
return self._token_matching(funcs, idx, end)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 223, in _token_matching
if func(token):
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\sql.py”, line 242, in
funcs = lambda tk: imt(tk, i, m, t)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\utils.py”, line 100, in imt
elif types and any(token.ttype in ttype for ttype in types):
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\utils.py”, line 100, in
elif types and any(token.ttype in ttype for ttype in types):
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\sqlparse\tokens.py”, line 19, in contains
return item is not None and (self is item or item[:len(self)] == self)

The above exception (maximum recursion depth exceeded in comparison) was the direct cause of the following exception:
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\cursor.py”, line 76, in fetchone
return self.result.next()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\query.py”, line 797, in next
result = next(self._result_generator)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\sql2mongo\query.py”, line 830, in iter
raise exe from e

The above exception (

Keyword: FAILED SQL: SELECT %(0)s AS "a" FROM "usuarios_user" WHERE "usuarios_user"."id" = %(1)s LIMIT 1

Params: (1, 2)
Version: 1.3.6
Sub SQL: None
FAILED SQL: None
Params: None
Version: None) was the direct cause of the following exception:
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\utils.py”, line 98, in inner
return func(*args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\cursor.py”, line 81, in fetchone
raise db_exe from e

The above exception () was the direct cause of the following exception:
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\core\handlers\exception.py”, line 56, in inner
response = get_response(request)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\core\handlers\base.py”, line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\options.py”, line 686, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\utils\decorators.py”, line 134, in _wrapped_view
response = view_func(request, *args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\views\decorators\cache.py”, line 62, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\sites.py”, line 242, in inner
return view(request, *args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\options.py”, line 1891, in add_view
return self.changeform_view(request, None, form_url, extra_context)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\utils\decorators.py”, line 46, in _wrapper
return bound_method(*args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\utils\decorators.py”, line 134, in _wrapped_view
response = view_func(request, *args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\options.py”, line 1751, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\options.py”, line 1797, in _changeform_view
form_validated = form.is_valid()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\forms\forms.py”, line 205, in is_valid
return self.is_bound and not self.errors
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\forms\forms.py”, line 200, in errors
self.full_clean()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\forms\forms.py”, line 439, in full_clean
self._post_clean()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\forms\models.py”, line 492, in post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\base.py”, line 1448, in full_clean
self.clean_fields(exclude=exclude)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\base.py”, line 1500, in clean_fields
setattr(self, f.attname, f.clean(raw_value, self))
File "C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\fields_init
.py", line 755, in clean
self.validate(value, model_instance)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\fields\related.py”, line 1088, in validate
if not qs.exists():
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\query.py”, line 1226, in exists
return self.query.has_results(using=self.db)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\sql\query.py”, line 592, in has_results
return compiler.has_results()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\sql\compiler.py”, line 1366, in has_results
return bool(self.execute_sql(SINGLE))
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\sql\compiler.py”, line 1409, in execute_sql
val = cursor.fetchone()
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\utils.py”, line 97, in inner
with self:
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\utils.py”, line 91, in exit
raise dj_exc_value.with_traceback(traceback) from exc_value
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\utils.py”, line 98, in inner
return func(*args, **kwargs)
File “C:\Users\lucas\AppData\Local\Programs\Python\Python311\Lib\site-packages\djongo\cursor.py”, line 81, in fetchone
raise db_exe from e

Exception Type: DatabaseError at /admin/espacios/espacio/add/
Exception Value:

Ok, nowhere in any of this have you mentioned or specified that Djongo is any part of this environment or process.

Are you using a Mongo DB managed by Djongo as your primary database? (Are these models being stored in Mongo?)

If so, then this is not a Django issue - you should raise this issue in one of the Djongo-related support channels.