Tengo un menú desplegable en un modelo y el usuario no debería poder cambiar el valor seleccionado. Encontré que un disabled
hace exactamente lo que necesito. Sin embargo, hay una rareza en esto:Django: Disabled Dropdown no envía información de vuelta a POST
La primera vez que se abre el formulario (GET) se selecciona el valor y el usuario no puede cambiar el valor. que es grande:
Pero tan pronto como hay un error de validación con un unrelated field
y la POST envía al usuario de vuelta a la misma forma, la información anterior se pierde. El menú desplegable deshabilitado de la clave externa ya no contiene ningún valor y es muy irritante.
hice algunas investigaciones y encontró algo en stackoverflow y parece cuando un widget ForeignKey-desplegable está desactivada, no se envían datos de vuelta en absoluto. Mientras que la validación puede ser anulada para no arrojar ningún error para el campo desplegable como lo explica el third answer here. Sin embargo, si CUALQUIER OTRO campo no relacionado arroja un error, entonces los datos se pierden, porque el menú desplegable deshabilitado nunca envió ningún dato a POST en primer lugar.
Es una situación complicada.
¿Hay alguna manera de pasar los datos dentro de la vista a la solicitud.POST? ¿o qué sugieres? Podría usar un readonly
en lugar de disabled
y eso funcionaría; sin embargo, el menú desplegable puede ser modificado por el usuario, lo que también es irritante.
¿Alguna idea? Muchas Gracias
edición:
pequeña corrección: Los datos no se pierde por completo. Más bien, la selección se establece incorrectamente al valor ficticio inicial.
<select id="id_form-0-deal_type" name="form-0-deal_type" disabled="disabled">
<option selected="selected" value="">---------</option>
<option value="1">deal 1</option>
<option value="2">deal 2</option>
</select>
ACTUALIZACIÓN:
La solución de Francis parece muy prometedor. Así que probé su segunda sugerencia y agregué un campo de entrada oculto en el html y le pasé el valor correcto al POST.
El problema ahora es cómo proceder. He tratado de agregar la entrada faltante en querydict de la forma del juego de formularios así (con el fin de establecer el valor desplegable correcta)
formset.forms[0].data['form-0-deal_type'] = formset.forms[0].data['form-0-hiddenfield']
Pero dice This QueryDict instance is immutable
La única manera de hacerlo es establecer que a través de Initials con formularios regulares. Desgraciadamente, estoy usando modelformsets, que doesn't support initials para formularios existentes.
Si no hay otra solución, comienzo a refactorizar mi modelformset en un formset regular. Todavía abierto para ideas ...
Informe final de actualización + Solución:
No hay necesidad de refactorizar modelformset en fomsets regulares. De hecho, no me gusta mucho hacer eso, ya que trae otros problemas consigo mismo. modelformsets maneja todo por ti y llena las partes faltantes.
El problema real es el hecho de que QueryDict son inmutables, pero esto se puede solucionar fácilmente copiándolos:
formset = deal_formset(request.POST, queryset=formset_query)
if formset.is_valid():
pass
else:
new_post = request.POST.copy()
deal_types = dict()
for k,v in new_post.items():
if k.startswith('hidden'):
deal_types[k[7:]]= v
for k,v in deal_types.iteritems():
new_post[k] = v
formset = deal_formset(new_post, queryset=formset_query)
Esto, más la solución de Francisco:
{{ formset.management_form }}
{% for fs in formset %}
{{ fs.id }}
<input type="hidden" name="hidden-{{ fs.prefix }}-deal_type" value="{{fs.deal_type.value}}" />
{{fs.deal_type}}
{% endfor %}
{% endif %}
solo hace maravillas. .. disfruta :)
"La información no se pierde por completo.Más bien, la selección se establece incorrectamente en el valor ficticio inicial. "- eso es b/c ese campo no se publica, por lo que se usa el valor predeterminado –