Il passaggio iniziale in Django ModelFormSet

Ho un modello formset che ho bisogno di passare la parola chiave iniziale per (avere alcuni valori iniziali nel formset, come la data fissata per oggi). Per quanto posso dire, il queryset argomento (che di default è YourModel.oggetti.tutti()) esegue l’override di questa capacità per vuoto iniziale forme per essere creato. Ho specificato il queryset come: YourModel.oggetti.nessuno(), che impedisce il riempimento, il formset con voci dal database, ma non riesco ancora a capire come passare iniziale in modo efficace. Ho bisogno di creare una sottoclasse di un metodo di ModelForm?

  • Si desidera modificare una particolare istanza del modello, ma non si desidera visualizzare i suoi valori esistenti e invece visualizzare diversi valori iniziali?
InformationsquelleAutor Vince | 2009-08-21

 

10 Replies
  1. 10

    Si sta passando un vuoto queryset per ModelFormset.

    ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2)
    formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                              initial=[{'name': 'Some Name'},
                                       {'name': 'Another Name'}])

    anzi, che è il modo per ottenere quello che vuoi. Ha senso passare un vuoto queryset, altrimenti i valori iniziali sostituirà il modello di database di valore.

    E se suppongo, si passa un non-vuoto queryset, e vuole ancora il tuo extra compilazione di moduli saranno i valori iniziali, è possibile ignorare il Formset.

    from django.forms.models import modelformset_factory  
    ExampleFormset = modelformset_factory(OpenIDProfile, extra=3)
    
    class myFormset(ExampleFormset):
    
        def _construct_form(self, i, **kwargs):
            """
            Instantiates and returns the i-th form instance in a formset.
            """
            if self.is_bound and i < self.initial_form_count():
                pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
                pk = self.data[pk_key]
                pk_field = self.model._meta.pk
                pk = pk_field.get_db_prep_lookup('exact', pk)
                if isinstance(pk, list):
                    pk = pk[0]
                kwargs['instance'] = self._existing_object(pk)
            if i < self.initial_form_count() and not kwargs.get('instance'):
                kwargs['instance'] = self.get_queryset()[i]
    
            defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)}
            if self.data or self.files:
                defaults['data'] = self.data
                defaults['files'] = self.files
            # Check to confirm we are not overwriting the database value.
            if not i in range(self.initial_form_count()) and self.initial:
                try:
                    defaults['initial'] = self.initial[i - self.initial_form_count()]
                except IndexError:
                    pass
            # Allow extra forms to be empty.
            if i >= self.initial_form_count():
                defaults['empty_permitted'] = True
            defaults.update(kwargs)
            form = self.form(**defaults)
            self.add_fields(form, i)        
            return form

    Nota: initial è la lista di dicts. La sua auspicabile disporre di elementi nella lista esattamente uguale al numero di extra.

    • Un trucco che mi ha fatto qui è che è necessario impostare extra maggiore o uguale al numero di elementi di dati iniziale. So che è la tua risposta, ma ho pensato che valeva la pena di evidenziare.
  2. 5

    Il modo migliore che ho trovato per farlo è quello di regolare manualmente il formset oggetto “extra” attributo dopo l’inizializzazione. Questo è stato testato e funziona in Django 1.9.

    ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1)
    formset = ExampleModelFormSet(initial=[{'name': 'Some Name'},
                                           {'name': 'Another Name'}])
    formset.extra = 3

    Questo farà sputare 3 forme (2 precompilato e 1 bianca).

    Se volete qualcosa di più dinamico (ad esempio, initial è una var calcolato da qualche altra parte), si può fare qualcosa di simile a questo:

    ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1)
    formset = ExampleModelFormSet(initial=initial)
    formset.extra += len(initial)

    Speranza che aiuta.

    • Senza il superamento di un queryset, questo è incasinato
  3. 2

    È ancora possibile il passaggio iniziale di un ModelFormSet.

    from django.forms.models import modelformset_factory
    from example.models import ExampleModel
    
    ExampleModelFormSet = modelformset_factory(ExampleModel)
    formset = ExampleModelFormSet(initial=[{'name': 'Some Name'},
                                           {'name': 'Another Name'}])

    Se questo non è ciò che il vostro dopo, si può spiegare la tua domanda in modo più.

    EDIT:

    ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2)
    formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                                  initial=[{'name': 'Some Name'},
                                           {'name': 'Another Name'}])
    • Per impostazione predefinita Django modello formset popolare stessi con i risultati di yourmodel.oggetti.tutti(). Questo può essere invertito con queryset=yourmodel.oggetti.nessuno(), ma questo ancora non consente valori iniziali. Qualcosa la queryset iniziale e parole chiave che rende questa non funziona.
    • Come fa a non funzionare, cosa non fa? Utilizzando il codice aggiornato ho un formset da un vuoto queryset e i valori iniziali compilato.
    • Sì.. questo è il modo per andare. Sono d’accordo.
  4. 1

    In Django 1.4 la regola è cambiata: il numero di iniziali per essere visualizzato corrisponde a “extra” parametro.
    https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

    Nel mio caso il conteggio dei parametri iniziali varia in modo dinamico, in modo
    Ho trovato il seguente modo:

    initial=[{'name': 'Some Name'},{'name': 'Another Name'}]
    formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                          initial=initial, extra=len(initial))
    
    
    class MyBaseFormSet(BaseModelFormSet):
        def __init__(self, *args, **kwargs):
            self.extra = kwargs.pop('extra', self.extra)
            super(MyBaseFormSet, self).__init__(*args, **kwargs)

    fornito, ExampleModelFormSet è basato su MyBaseFormSet

  5. 0

    Una soluzione semplice potrebbe essere quello di passare un form che si modelform() per un formset (piuttosto che modelformset).

    Che modo è possibile impostare i valori iniziali della forma.

    • Puoi approfondire questo? Io non sono sicuro di capire cosa intendi.
  6. 0

    È possibile modificare i dati iniziali in seguito.

    Per esempio:

    # Construct the FormSet class
    ExampleFormSet = modelformset_factory(ParentModel, ChildModel)
    
    # Set the initial data
    initial_data = {'field1': 1}
    for form in ExampleFormSet.extra_forms:
        for field in form.fields:
            field.initial = initial_data[field.name]
    • Quando provo che (con formset_factory), mi 'str' object has no attribute 'initial' che Cosa potrebbe essere sbagliato?
    • si prega di verificare che form.fields restituisce. Questo codice potrebbe essere bisogno di una correzione.
    • in python 2.7 (almeno) iterare su un dizionario gies solo le chiavi non dati
    • forma.i campi non funziona.
  7. 0

    In modo semplice come passare i dati iniziali con lo stesso numero di formati extra:

    MyModelFormSet = lambda *a, **kw: modelformset_factory(MyModel, extra=kw.pop('extra', 1))(*a, **kw)

    Utilizzo in vista:

    initial=[{'name': 'Some Name'},{'name': 'Another Name'}
    formset = MyModelFormSet(queryset=MyModel.objects.none(), initial, extra=len(initial))})
  8. 0

    Dopo due giorni trovato questo: http://streamhacker.com/2010/03/01/django-model-formsets/

    def custom_field_callback(field):
        return field.formfield(required=False)
    
    FormSet = modelformset_factory(model, formfield_callback=custom_field_callback)
    
    def custom_field_callback(field):
        if field.name == 'optional':
            return field.formfield(required=False)
        elif field.name == 'text':
            return field.formfield(widget=Textarea)
        elif field.name == 'integer':
            return IntegerField()
        else:
            return field.formfield()

Lascia un commento