2009-12-13 13 views

risposta

2

Ho avuto questo problema ed ho fatto un nuovo widget:

from django.forms.widgets import Select 
from django.utils.safestring import mark_safe 
class PrepolutatedSelect(Select): 
    def render(self, name, value, attrs=None, choices=()): 
     if value is None: value = '' 
     if value == '': 
      value = int(name.split('-')[1])+1 
     final_attrs = self.build_attrs(attrs, name=name) 
     output = [u'<select%s>' % flatatt(final_attrs)] 
     options = self.render_options(choices, [value]) 
     if options: 
      output.append(options) 
     output.append('</select>') 
     return mark_safe(u'\n'.join(output)) 

Forse questo funzionerà anche per te.

+0

Ho un problema simile all'OP. Sto provando a creare un formset con diverse forme, con ogni modulo che ha il proprio set unico di opzioni per un elemento select (ad esempio "scelte"). Non riesco a capire come questa soluzione possa essere d'aiuto. Mi sto perdendo qualcosa? – ACPrice

10

È necessario utilizzare la tecnica descritta in this post per poter passare i parametri. Credito a quell'autore per un post eccellente. A raggiungere questo in varie parti:

una forma consapevole che sta per raccogliere ulteriori parametri

Esempio dalla questione legata:

def __init__(self, *args, **kwargs): 
    someeobject = kwargs.pop('someobject') 
    super(ServiceForm, self).__init__(*args, **kwargs) 
    self.fields["somefield"].queryset = ServiceOption.objects.filter(
                  somem2mrel=someobject) 

Oppure è possibile sostituire il secondo codice con

self.fields["somefield"].initial = someobject 

direttamente, e funziona.

Una configurazione curry forma di inizializzazione:

formset = formset_factory(Someform, extra=3) 
formset.form = staticmethod(curry(someform, somem2mrel=someobject)) 

che si ottiene per il passaggio di parametri modulo personalizzato. Ora quello che serve è:

Un generatore di acquisire i tuoi diversi parametri iniziali

Sto usando questo:

def ItemGenerator(Item): 
    i = 0 
    while i < len(Item): 
     yield Item[i] 
     i += 1 

Ora, posso fare questo:

iterdefs = ItemGenerator(ListofItems) # pass the different parameters 
             # as an object here 
formset.form = staticmethod(curry(someform, somem2mrel=iterdefs.next())) 

Ehi, presto. Ogni valutazione del metodo form viene valutata in parti che passano in un parametro iterato. Possiamo scorrere su ciò che ci piace, quindi sto usando questo fatto per scorrere su un insieme di oggetti e passare il valore di ognuno come un parametro iniziale diverso.

+0

ehi! Penso che la tua risposta potrebbe risolvere il problema che ho affrontato in questa domanda http://stackoverflow.com/questions/6123278/same-form-different-variables-how-to-implement. Ma in realtà non capisco cosa stia succedendo – pavid

+1

Ho provato a utilizzare questo approccio ma non riesco a far scorrere l'iteratore su ogni chiamata. Il mio codice: 'DecorationFileFormSet.form = staticmethod (curry (DecorationFileForm, filetype = counter.next()))' crea form dove l'attributo filetype è 1 ogni volta. contatore è un'istanza di 'itertools.count (1)' –

+0

Chiunque ha già una soluzione? Anche il generatore non funziona (non itera affatto) anche per me. – wgx731

2

Sulla risposta di Antonio Vennard, io non sono sicuro di quello che versione di Python/Django che sta usando, ma non ho potuto ottenere il generatore di lavorare nel metodo curry sia. Sono attualmente su python2.7.3 e django1.5.1. Invece di usare un generatore personalizzato, ho finito con l'incorporare lo iter() in un elenco di cose per creare un iteratore e passare l'iteratore stesso nel metodo curry e chiamare next() su di esso nello Form__init__().Qui è la mia soluzione:

# Build the Formset: 
my_iterator = iter(my_list_of_things) # Each list item will correspond to a form. 
Formset = formset_factory(MyForm, extra=len(my_list_of_things)) 
Formset.form = staticmethod(curry(MyForm, item_iterator=my_iterator)) 

e nella forma:

# forms.py 
class MyForm(forms.Form): 
    def __init__(self, *args, **kwargs): 
     # Calling next() on the iterator/generator here: 
     list_item = kwargs.pop('item_iterator').next() 

     # Now you can assign whatever you passed in to an attribute 
     # on one of the form elements. 
     self.fields['my_field'].initial = list_item 

alcune cose fondamentali che ho trovato erano che è necessario specificare un valore di 'extra' nel formset_factory o utilizzare il initial kwarg su il formset per specificare una lista che corrisponde alla lista che si passa all'iteratore (Nell'esempio precedente passo il len() dell'elenco my_list_of_things a 'extra' kwarg a formset_factory). Questo è necessario per creare effettivamente un numero di moduli nel formset.

33

Se hai commesso lo stesso errore di me, hai leggermente confuso la documentazione.

Quando ho visto la prima volta questo esempio ...

formset = ArticleFormSet(initial=[ 
{'title': 'Django is now open source', 
    'pub_date': datetime.date.today(),} 
]) 

ho pensato che ogni modulo viene dato lo stesso insieme di dati iniziali sulla base di un dizionario.

Tuttavia, se si guarda attentamente, si vedrà che al formset viene effettivamente passata una lista di dizionari.

Per impostare diversi valori iniziali per ogni modulo in un formset, è sufficiente passare un elenco di dizionari contenenti i diversi dati.

Formset = formset_factory(SomeForm, extra=len(some_objects) 
some_formset = FormSet(initial=[{'id': 'x.id'} for x in some_objects]) 
+2

Questo sembra essere il modo più semplice per farlo, e il modo Django predefinito per farlo, e mette in luce l'idea sbagliata che l'OP aveva. Dovrebbe essere la risposta migliore. – ACPrice

+1

Si noti che questo renderà 'ArticleFormSet' un [modulo non associato] (https://docs.djangoproject.com/en/1.10/topics/forms/#bound-and-unbound-form-instances), poiché i valori iniziali sovrascriveranno i valori restituiti dall'articolo queryset. –

Problemi correlati