2010-06-07 20 views
20

nel mio progetto Django (1.2), desidopolare un campo in un modello, ma il mio nuovo valore viene ignorato. Questo è il frammento:Sovrascrivere il valore iniziale in ModelForm

class ArtefactForm(ModelForm): 
    material = CharField(widget=AutoCompleteWidget('material', force_selection=False)) 

    def __init__(self, *args, **kwargs): 
     super(ArtefactForm, self).__init__(*args, **kwargs) 
     self.fields['material'].initial = 'Test' 

ho anche provato con self.base_fields, ma nessun effetto: c'è sempre il database di valore che visualizza in forma. Qualche idea?

risposta

39

Prova questo:

def __init__(self, *args, **kwargs): 
    initial = kwargs.get('initial', {}) 
    initial['material'] = 'Test' 
    kwargs['initial'] = initial 
    super(ArtefactForm, self).__init__(*args, **kwargs) 
+0

perfetto, grazie. – schneck

10

vecchia questione, ma l'aggiunta di una risposta descrittiva come credo che sarebbe utile per qualche nuovo sviluppatore.

Ho anche provato con self. base_fields, ma nessun effetto: c'è sempre il valore del database visualizzato nel modulo. Qualche idea?

Se un modulo è "inizializzato" forma, sia: -

  1. utilizzando initial argomento (es. YourModelFrom(initial={'filed1': variable}) — generalmente il caso, quando si vuole passare i valori iniziali calcolati in modo dinamico per alcuni campi) . Riferimento Setting Initial Values

    o

  2. utilizzando instance argomento (ad es. YourModelFrom(instance=model_object) — solitamente il caso, quando si vuole aggiornare un oggetto esistente un'istanza del modello). Riferimenti leggono di ModelFrom save() method

    Nota:
    classe eredita `BaseModelFrom` classe. La classe `BaseModelFrom` eredita la classe `BaseForm`.
    2 L'argomento instance viene aggiunto in `BaseModelFrom` costruttore della classe, quando si assegna un oggetto del modello un'istanza classe instance argomento (quindi instance is not None) allora `BaseModelFrom` costruzione chiama model_to_dict() e aggiornamenti initial argomento prima chiamare costruttore della super-classe. Controllare def __init__ in classe BaseModelFrom

assegnando valore iniziale di un campo in modo esplicito (come mostrato nel codice di OP in questione) non effetto, questo è dovuto al modo in cui _clean_fields metodo è scritto in BaseFrom classe.

Codice Snip:

def _clean_fields(self): 
    for name, field in self.fields.items(): 
     value = field.widget.value_from_datadict(
       self.data, self.files, self.add_prefix(name)) 
     try: 
      if isinstance(field, FileField): 
       initial = self.initial.get(name, field.initial) # <- Check 
       value = field.clean(value, initial) 
      else: 

Secondo riga di codice initial = self.initial.get(name, field.initial), se il valore iniziale per il campo è dato in initial dict quindi valore assegnato a field.initial è non utilizzato.

[RISPOSTA]:

Anche se, @ Daniel risposta è perfettamente corretto, ma si può anche come un altro modo per ottenere lo stesso effetto utilizza la self.initial:

def __init__(self, *args, **kwargs): 
    super(ArtefactForm, self).__init__(*args, **kwargs) 
    self.initial['material'] = 'Test' 

dargli una prova !!

self.initial non è nient'altro che è il contrario. Controllare il codice __init__ in BaseForm:

class BaseForm(object): 
    def __init__(........ 
       ........): 
     : 
     self.prefix = prefix 
     self.initial = initial or {} # <-- Notice 
     self.error_class = error_class 
     : 

Nota: Non ho trovato alcuna documentazione relativa a utilizzare l'attributo iniziale, ho appena esplorato il codice di base e l'ho usato.

Edit: il comportamento riportato in questione è anche documentato in Django Modello

Dynamic initial values

Form.initial

Si noti che se un Field definisce initial e si includono initial quando istanziare il modulo, quindi il secondo initial avrà la precedenza. In questo esempio, initial viene fornito sia a livello di campo e al livello di istanza modulo, e il secondo ottiene la precedenza:

>>> from django import forms 
>>> class CommentForm(forms.Form): 
...  name = forms.CharField(initial='class') 
...  url = forms.URLField() 
...  comment = forms.CharField() 
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) 
>>> print(f) 
<tr><th>Name:</th><td><input type="text" name="name" value="instance" /> 
<tr><th>Url:</th><td><input type="url" name="url" /></td></tr> 
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> 

PS: A proposito, il punto 2 nelle mie risposte dicono differenza tra initial e argomento instance. Il loro è un altro argomento chiave-valore data - i valori in tali trigger formano convalide. leggi questo Difference between Django Form 'initial' and 'bound data'?.

+0

** Nota: ** In forma associata, 'data' (la query dict) avrà la precedenza sul valore del campo inizializzato. Codice di controllo: ['def value (self)'] (https://github.com/django/django/blob/master/django/forms/forms.py#L610) e metodo ['def bound_data (self, data, iniziale) '] (https://github.com/django/django/blob/master/django/forms/fields.py#L165) - questo ti aiuterà se hai un valore per un campo calcolato dinamicamente e il archiviato è ['disabilitato'] (http://stackoverflow.com/a/1424453/1673391). Fammi sapere se qualcuno ha bisogno di aiuto su questo aggiornerò questa risposta! –

+0

Ottima risposta, grazie! Per quanto riguarda l'impostazione del valore iniziale, vorrei aggiungere una soluzione [ho trovato] (https://stackoverflow.com/a/22390638/2996101): 'self.fields [field_name] .initial = field_value' – raratiru

Problemi correlati