django set ModelChoiceField "to_field_name" a múltiples columnas
Quiero proporcionar varios nombres de campo en el modelo de Django Elección de Field to_field_name
algo como
field1 = forms.ModelChoiceField(queryset=myModel.objects.all(), required=False,
empty_label="--------",
to_field_name=["col1, col2"],
widget=forms.Select(attrs={'class':'form-control'}),
)
Tengo un modelo como
class Codes(models.Model):
item_code = models.CharField(max_length=50)
item_name = models.CharField(max_length=50)
def __str__(self):
return self.item_code + self.item_name
Ahora puedo queryset
como
field1 = forms.ModelChoiceField(queryset=Codes.objects.all(), required=False,
empty_label="--------",
widget=forms.Select(attrs={'class':'form-control'}),
)
Y conseguiré la combinación de dos campos en mi select
Opciones de etiqueta
todo funciona pero cuando abro la página de edición, el cuadro selecto no muestra el valor seleccionado predeterminado
También quiero una combinación de campos porque cuando item_code
repite en la base de datos, to_field_name
da un error.
Pregunta hecha hace 3 años, 5 meses, 0 días - Por byteninja8245
3 Respuestas:
-
Creo que estás interpretando
to_field_name
mal:Según el sitio web de Django (Django to_field_name explicado):
Este argumento opcional se utiliza para especificar el campo para utilizar como el valor de las opciones en el widget del campo. Asegúrese de que es un campo único para el modelo, de lo contrario el valor seleccionado podría coincidir con más de un objeto. Por defecto se establece en Ninguno, en cuyo caso se utilizará la clave principal de cada objeto...
Lo que significa que puedes usar
to_field_name
para abordar el objeto del formulario en HTML. Pero no dice nada sobre múltiplesto_field_name
valores. Normalmente la clave principal se utiliza para abordar el objeto. Si fijas elto_field_name
entonces ese campo será usado.Para realmente agregar datos en
modelChoiceField
Tienes que hacer algo así.class CustomForm(ModelForm): muscles = forms.ModelMultipleChoiceField( queryset=None, to_field_name='name', required=False,) def __init__(self, *args, **kwargs): super(CustomForm, self).__init__(*args, **kwargs) self.fields['name'].queryset = Users.objects.all()
Respondida el Dec 17, 2020 a las 08:18 - por scriptsorcerer
Votos positivos: 0 | Votos negativos: 0 -
Para lograr lo que deseas, puedes crear un método personalizado en tu formulario que maneje la lógica de combinación de los campos
item_code
eitem_name
y use este método en el widget. Esto te permitirá mostrar la opción seleccionada correctamente en el formulario de edición.Aquí te dejo un ejemplo de cómo podrías hacerlo:
python from django import forms from .models import Codes class CustomModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return f"{obj.item_code} - {obj.item_name}" class CustomForm(forms.Form): field1 = CustomModelChoiceField(queryset=Codes.objects.all(), required=False, empty_label="--------", widget=forms.Select(attrs={'class':'form-control'}), )
En este caso,
CustomModelChoiceField
hereda deModelChoiceField
y sobrescribe el métodolabel_from_instance
para combinar los campositem_code
eitem_name
. Luego, en el formularioCustomForm
, se utiliza este campo personalizadofield1
.Ahora, en tu template donde renderizas el formulario, asegúrate de pasar la instancia del objeto correspondiente al campo
field1
para que el valor seleccionado se muestre correctamente al abrir la página de edición.Espero que esta solución sea de ayuda. ¡Déjame saber si tienes alguna otra pregunta!
Respondida el Dec 18, 2020 a las 08:21 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Para especificar múltiples columnas en el parámetro
to_field_name
deModelChoiceField
en Django, utiliza el siguiente formato:to_field_name='
, ,...' En tu caso, para utilizar las columnas
item_code
eitem_name
como nombres de visualización, puedes usar el siguiente código:python field1 = forms.ModelChoiceField( queryset=Codes.objects.all(), required=False, empty_label="--------", to_field_name='item_code,item_name', widget=forms.Select(attrs={'class': 'form-control'}), )
Solución al problema de edición:
El problema con el valor predeterminado que no se muestra en la página de edición se debe a que Django no puede identificar de forma única el objeto seleccionado cuando utilizas múltiples columnas en
to_field_name
. Para solucionar esto, puedes anular el métodoget_initial_for_field
en tu formulario de la siguiente manera:python class MyForm(forms.ModelForm): field1 = forms.ModelChoiceField( queryset=Codes.objects.all(), required=False, empty_label="--------", to_field_name='item_code,item_name', widget=forms.Select(attrs={'class': 'form-control'}), ) def get_initial_for_field(self, field, field_name): if field_name == 'field1' and self.instance.pk: return self.instance.item_code, self.instance.item_name return super().get_initial_for_field(field, field_name)
Prevención de duplicados:
Para evitar errores cuando
item_code
se repite en la base de datos, puedes utilizar un campo único en tu modeloCodes
, comouuid
, y luego utilizar ese campo comoto_field_name
:class Codes(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) item_code = models.CharField(max_length=50, unique=True) item_name = models.CharField(max_length=50) def __str__(self): return self.item_code + self.item_name
python field1 = forms.ModelChoiceField( queryset=Codes.objects.all(), required=False, empty_label="--------", to_field_name='uuid', widget=forms.Select(attrs={'class': 'form-control'}), )
Respondida el Dec 18, 2020 a las 08:29 - por Gemini
Votos positivos: 0 | Votos negativos: 0