2010-03-09 1 views
30

Questi formati stanno esibendo esattamente il di fronte al comportamento che desidero.Formset Django: effettuare prima la richiesta?

La mia opinione è impostato in questo modo:

def post(request): # TODO: handle vehicle formset 
    VehicleFormSetFactory = formset_factory(VehicleForm, extra=1) 
    if request.POST: 
     vehicles_formset = VehicleFormSetFactory(request.POST) 
    else: 
     vehicles_formset = VehicleFormSetFactory() 

E il mio modello è simile al seguente:

<div id="vehicle_forms"> 
     {{ vehicles_formset.management_form }} 
     {% for form in vehicles_formset.forms %} 
      <h4>Vehicle {{forloop.counter}}</h4> 
      <table> 
       {% include "form.html" %} 
      </table> 
     {% endfor %} 
    </div> 

In questo modo si genera inizialmente solo 1 modulo, come voglio. Ma voglio che sia richiesto un solo modulo!

Quando aggiungo dinamicamente moduli vuoti con JavaScript e vehicles_formset.empty_form sono richiesti tutti quei moduli aggiuntivi, che non desidero.

Dalla documentazione:

Il formset è abbastanza intelligente per ignorare le forme extra che non sono stati modificati.

Questo è il comportamento che mostra il primo modulo (non quello che voglio) ma non il comportamento che i moduli aggiuntivi stanno esibendo (cosa voglio).

C'è qualche attributo che posso modificare per rendere almeno un modulo richiesto?

+0

@ MPit anche se sono in ritardo per la festa, mi chiedevo come fare per una questione leggermente diversa che sto affrontando la mia domanda qui (https://stackoverflow.com/questions/44159559/need-to-have-a-required-and-optional-fields-in-django-formset) – dungu

+0

@kedric Stai chiedendo il ragazzo sbagliato Non ho usato Django da poco dopo aver postato questa domanda. – mpen

+0

ooh, ok fratello grazie per la risposta – dungu

risposta

65

trovato una soluzione migliore:

class RequiredFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     super(RequiredFormSet, self).__init__(*args, **kwargs) 
     for form in self.forms: 
      form.empty_permitted = False 

quindi creare il formset come questo:

MyFormSet = formset_factory(MyForm, formset=RequiredFormSet) 

ho davvero non so perché questa non era un'opzione per cominciare .. . ma comunque. Ci sono volute solo poche ore della mia vita per capirlo.

Questo renderà tutte le forme richieste.È possibile effettuare solo il primo richiesto impostando self.forms[0].empty_permitted a False.

+1

Questa è la soluzione a una delle parti più fastidiose di Django, è inspiegabile perché questo non fa parte della documentazione – YPCrumble

+0

Per qualche motivo, ottengo un errore KeyError quando provo a impostare un modulo specifico su empty_permitted. Ad esempio "form [0] .empty_permitted = False" restituisce un errore. –

+0

@Zorpix dovrebbe essere 'self.forms [0]' Penso, supponendo che tu abbia almeno un modulo. – mpen

1

Oh penso di vedere. Prova questo:

from django.forms.formsets import BaseFormSet, formset_factory 
class OneExtraRequiredFormSet(BaseFormSet): 
    def initial_form_count(self): 
     return max(super(OneExtraRequiredFormSet,self).initial_form_count() - 1,0) 

VehicleFormSetFactory = formset_factory(VehicleForm, formset=OneExtraRequiredFormSet, extra=1) 

== risposta originale al di sotto ==

Quando si dice "almeno fare una forma necessaria", suppongo che voi dire "fare solo una forma più richiesto, indipendentemente da quanti hanno stato aggiunto tramite javascript ".

È necessario disporre di un input nascosto sulla pagina che contenga il numero di moduli aggiunti tramite javascript, quindi utilizzare quel numero, meno 1, come valore da passare come attributo extra al costruttore di moduli. .

+0

Non proprio ... ignorando il JavaScript per ora, viene visualizzato un solo modulo (extra = 1, nessun dato iniziale). Quella * una * forma non è richiesta - voglio che sia. Qualsiasi modulo aggiunto tramite JS dovrebbe * non * essere richiesto, mai. – mpen

+0

La mia modifica è utile? – Wogan

+0

Questo ha un comportamento bizzarro. Quando lascio il modulo vuoto e lo invio, ne aggiunge un altro e inserisce errori nel nuovo modulo, e ancora non convalida il primo. – mpen

9

Bene ... questo rende necessario il primo modulo.

class RequiredFormSet(BaseFormSet): 
    def clean(self): 
     if any(self.errors): 
      return 
     if not self.forms[0].has_changed(): 
      raise forms.ValidationError('Please add at least one vehicle.') 

unico "problema" è che se ci sono 0 forme, allora il metodo clean non sembra ottenere chiamato a tutti, quindi non so come controllare se ci sono 0. davvero .. .questo non dovrebbe mai accadere però (tranne che il mio JS ha un bug in esso, che consente di rimuovere tutti i moduli).

+1

Se si utilizza questo modulo per modificare un gruppo esistente di oggetti, sarà sempre necessario aggiornare il primo. Questo è adatto solo per la creazione, non l'aggiornamento. –

+0

@Daniel Palm, hai una soluzione? Ho anche lo stesso problema. –