Ho un menu a discesa in un modello e l'utente non dovrebbe essere in grado di modificare il valore selezionato. Ho trovato che un disabled
fa esattamente ciò di cui ho bisogno. Tuttavia c'è una stranezza in questo:Django: menu a discesa disattivato non invia informazioni al POST
La prima volta che si apre il modulo (GET) il valore è selezionato e l'utente non può modificare il valore. che è grande:
Ma non appena v'è un errore di convalida con una unrelated field
e il POST invia l'utente alla stessa forma, le informazioni precedenti si perde. Il menu a discesa foreignkey disabled non contiene più alcun valore ed è molto irritante.
ho fatto qualche ricerca e ho trovato qualcosa su StackOverflow e sembra quando un widget ForeignKey-discesa è disattivato, i dati non vengono inviati indietro a tutti. Mentre la convalida può essere annullata per non generare alcun errore per il campo a discesa come spiegato da third answer here. Tuttavia, se QUALSIASI ALTRA campo non correlato genera un errore, i dati vengono persi, poiché il menu a discesa disabilitato non ha mai inviato alcun dato al POST al primo posto.
È una situazione complicata.
C'è un modo per passare i dati all'interno della vista alla richiesta.POST? o cosa suggerisci? Potrei usare uno readonly
invece di disabled
e ciò funzionerebbe, tuttavia il dropdown può essere modificato dall'utente, che è anche irritante.
Qualche idea? Molte grazie
edit:
Piccola correzione: I dati non è completamente perso. Piuttosto, la selezione è impostata erroneamente sul valore fittizio iniziale.
<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>
UPDATE:
La soluzione da Francesco sembra molto promettente. Così ho provato il suo secondo suggerimento e ho aggiunto un campo di input nascosto nell'html e ho inserito il valore corretto nel POST.
Il problema è ora come procedere. Ho provato ad aggiungere la voce mancante in QueryDict del modulo del formset come questo (al fine di impostare il valore a discesa corretto)
formset.forms[0].data['form-0-deal_type'] = formset.forms[0].data['form-0-hiddenfield']
ma dice This QueryDict instance is immutable
L'unico altro modo per farlo è la creazione di esso attraverso Initials con formulari regolari. Purtroppo sto usando modelformsets, che è doesn't support initials per i moduli esistenti.
Se non c'è altra soluzione, inizio a refactoring myformformset in un formset regolare. Ancora aperto alle idee ...
aggiornamento finale + Soluzione:
Non v'è alcuna necessità di refactoring modelformset in fomsets regolari. In effetti, lo scoraggio molto, poiché porta altri problemi con se stesso. modelformsets gestisce tutto per te e riempie le parti mancanti.
Il vero problema è il fatto che QueryDict sono immutabili, ma questo può essere facilmente risolto copiandoli:
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)
Questo, più la soluzione di Francesco:
{{ 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 %}
funziona a meraviglia. .. enjoy :)
"I dati non sono completamente persi.Piuttosto, la selezione è impostata erroneamente sul valore fittizio iniziale. "- che è b/c che il campo non viene pubblicato, quindi viene utilizzato il valore predefinito –