2010-06-07 18 views
20

in meinem Django (1.2) -Projekt überschreiben, möchte ich ein Feld in einem Modell vorzufüllen, aber mein neuer Wert wird ignoriert. Dies ist der Code-Schnipsel:Initialwert 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' 

ich auch mit self.base_fields versucht, aber keine Wirkung: Es gibt immer den Datenbank-Wert in der Form angezeigt wird. Irgendwelche Ideen?

Antwort

39

Versuchen Sie folgendes:

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

perfekt, danke. – schneck

10

alte Frage, aber das Hinzufügen einer deskriptiven Antwort, wie ich es glaube, für einige neue Entwickler nützlich sein würde.

Ich versuchte auch mit self. base_fields, aber keine Wirkung: Im Formular wird immer der Datenbankwert angezeigt. Irgendwelche Ideen?

Wenn ein Formular "initialisiert" Form - entweder

  1. mit initial Argument (. ZB YourModelFrom(initial={'filed1': variable}) — der Regel der Fall, wenn Sie dynamisch berechneten Anfangswerte für einige Felder übergeben möchten) . Referenz Setting Initial Values

    oder

  2. mit instance Argument (zB. YourModelFrom(instance=model_object) — in der Regel der Fall, wenn man will, eine bestehende Modellinstanz Objekt aktualisieren). Referenzen lesen ModelFrom des save() method

    Hinweis:
    Klasse erbt `BaseModelFrom` Klasse. Die `BaseModelFrom` Klasse erbt `BaseForm` Klasse.
    2 Das Argument instance wird in `BaseModelFrom` Klassenkonstruktors hinzugefügt, wenn wir ein Modell Klasseninstanz Objekt instance Argument (daher instance is not None) dann `BaseModelFrom` Konstruktor ruft model_to_dict() und Updates initial Argument zuweisen, bevor Superklasse Konstruktor aufzurufen. Prüfen def __init__ in BaseModelFrom Klasse

Dann Anfangswert auf ein Feld zuweisen explizit (wie im OP der betreffenden Code dargestellt) nicht wirksam, ist dies aufgrund der Art und Weise _clean_fields Methode in BaseFrom Klasse geschrieben wird.

-Code 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: 

Laut Codezeile initial = self.initial.get(name, field.initial), wenn Anfangswert für das Feld in initial dict gegeben wird dann field.initial zugewiesenen Wert ist nicht verwendet.

[ANTWORT]:

Obwohl @ Daniel Antwort vollkommen richtig ist, aber man kann wie eine andere Art und Weise auch gleiche Wirkung zu erzielen, wird mit self.initial:

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

es versuchen !!

self.initial ist nichts anderes als das Diktat, das wir in Argument übergeben. Überprüfen Code __init__ in BaseForm:

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

Hinweis: ich keine Unterlagen gefunden haben im Zusammenhang Anfangs Attribut zu verwenden, ich erforschte nur den Basiscode und verwendet es.

Edit: das Verhalten in Frage berichtet auch in Django Modell dokumentiert

Dynamic initial values

Form.initial

Beachten Sie, dass, wenn ein Field definiert initial und Sie umfassen initial wenn das Formular instanziiert wird, dann letzteres initial wird Vorrang haben. In diesem Beispiel wird initial sowohl auf der Feldebene zur Verfügung gestellt und bei der Form Instanzebene, und dieser erhält Vorrang:

>>> 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: Btw, Punkt 2 in meinen Antworten sagen Unterschied zwischen initial und instance Argument. Das ist ein weiteres Schlüsselwertargument data - Werte, die Formvalidierungen auslöst. Lesen Sie diese Difference between Django Form 'initial' and 'bound data'?.

+0

** Hinweis: ** In gebundener Form haben 'Daten' (das Abfrage-Dict) Vorrang vor dem Wert des initialisierten Feldes. Überprüfen Sie den Code: ['def value (self)'] (https://github.com/django/django/blob/master/django/forms/forms.py#L610) und Methode ['def bound_data (self, data, Initial) '] (https://github.com/django/django/blob/master/django/forms/fields.py#L165) - dies wird Ihnen helfen, wenn Sie einen Wert für ein Feld os dynamisch berechnet haben und die abgelegt ist ['deaktiviert'] (http://stackoverflow.com/a/1424453/1673391). Lassen Sie mich wissen, wenn jemand Hilfe dazu benötigt, werde ich diese Antwort aktualisieren! –

+0

Große Antwort, danke! Bezüglich der Anfangswerteinstellung möchte ich eine Lösung hinzufügen [Ich fand] (https://Stackoverflow.com/a/22390638/2996101): 'self.fields [field_name] .initial = field_value' – raratiru