Django hat Standardformularwerte festgelegt

241

Ich habe ein Modell wie folgt:

class TankJournal(models.Model):
    user = models.ForeignKey(User)
    tank = models.ForeignKey(TankProfile)
    ts = models.IntegerField(max_length=15)
    title = models.CharField(max_length=50)
    body = models.TextField()

Ich habe auch ein Modellformular für das obige Modell wie folgt:

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput()) 

    class Meta:
        model = TankJournal
        exclude = ('user','ts')

Ich möchte wissen, wie der Standardwert für dieses ausgeblendete Tankfeld festgelegt wird. Hier ist meine Funktion, um das Formular bisher anzuzeigen / zu speichern:

def addJournal(request, id=0):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')

    # checking if they own the tank
    from django.contrib.auth.models import User
    user = User.objects.get(pk=request.session['id'])

    if request.method == 'POST':
        form = JournalForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)

            # setting the user and ts
            from time import time
            obj.ts = int(time())
            obj.user = user

            obj.tank = TankProfile.objects.get(pk=form.cleaned_data['tank_id'])

            # saving the test
            obj.save()

    else:
        form = JournalForm()

    try:
        tank = TankProfile.objects.get(user=user, id=id)
    except TankProfile.DoesNotExist:
        return HttpResponseRedirect('/error/')
Mike
quelle

Antworten:

401

Sie können mit Anfang , die erklären hier

Sie haben zwei Möglichkeiten, den Wert beim Aufrufen des Formularkonstruktors zu füllen:

form = JournalForm(initial={'tank': 123})

oder legen Sie den Wert in der Formulardefinition fest:

tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 
Sergey Golovchenko
quelle
Und wie wird diese Variable initialan das eigentliche Formular übergeben? Müssen wir im eigentlichen Formularmodell als Parameter / Argument schreiben?
mgPePe
2
@ Bharal Es ist Magie. ;-) (Oder besser gesagt, Django-Formularkonstruktoren verstehen die spezielle "anfängliche" Variable und durchlaufen ihren Inhalt, ohne dass Sie etwas extra tun müssen). Persönlich ziehe ich es vor, Standardwerte in der Formulardefinition anzugeben und den Mechanismus initial = ... nur zu verwenden, wenn der gewünschte Standard ein dynamischer Wert ist (z. B. etwas, das von einem Benutzer eingegeben wurde oder auf dessen Anmeldung, geografischem Standort usw. basiert).
Richard J Foster
66
Initiale ist nicht Standard. Der Anfangswert gilt nicht, wenn das Formular gebunden wurde :(.
Clime
4
Kommentieren Sie hier, um einen anderen Anwendungsfall zu erwähnen, in dem diese Lösung des anfänglichen Parameters hilfreich ist: Wenn Sie einen Registrierungslink an jemanden senden, wenn Sie die E-Mail / ID oder einen anderen Berechtigungsnachweis auf dem Registrierungsformular vorab ausfüllen möchten, können Sie diesen in diesem Fall nicht einschreiben Das Modell selbst ist dynamisch, stattdessen müssen Sie den Konstruktor mit dem Anfangsparameter aufrufen, wie von @ umnik700 erwähnt. Funktioniert super!
Keshav Agrawal
1
@Phlip: Nicht überschreiben View.get_form, um die Anfangsdaten festzulegen . Jede CBV mit einem FormMixin (im Grunde alle CBVs, die Daten erstellen oder bearbeiten) kann entweder eine initialVariable auf Klassenebene verwenden (für unveränderte Standardeinstellungen) oder Sie können überschreiben FormMixin.get_initial(), um ein Diktat der Anfangswerte zurückzugeben, die an den Konstruktor des Formulars übergeben werden sollen (für dynamische Standardeinstellungen) .)
GDorn
29

Andere Lösung: Setzen Sie die Initiale nach dem Erstellen des Formulars:

form.fields['tank'].initial = 123
Andreas Zwerger
quelle
Diese Arbeit für meinen Bedarf, nur ein Feld im Formular initiieren. Danke.
bl4ckb1rd
11

Ich hatte diese andere Lösung (ich poste sie, falls jemand anderes wie ich die folgende Methode aus dem Modell verwendet):

class onlyUserIsActiveField(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(onlyUserIsActiveField, self).__init__(*args, **kwargs)
        self.fields['is_active'].initial = False

    class Meta:
        model = User
        fields = ['is_active']
        labels = {'is_active': 'Is Active'}
        widgets = {
            'is_active': forms.CheckboxInput( attrs={
                            'class':          'form-control bootstrap-switch',
                            'data-size':      'mini',
                            'data-on-color':  'success',
                            'data-on-text':   'Active',
                            'data-off-color': 'danger',
                            'data-off-text':  'Inactive',
                            'name':           'is_active',

            })
        }

Die Initiale wird in der __init__Funktion als definiertself.fields['is_active'].initial = False

Izuzvo
quelle
0

Ich hoffe das kann dir helfen:

form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id
Code47
quelle
0

Wie in Django-Dokumenten erklärt , initialist dies nicht der Falldefault .

  • Der Anfangswert eines Feldes soll in einem HTML angezeigt werden. Wenn der Benutzer diesen Wert löscht und schließlich einen leeren Wert für dieses Feld zurücksendet, geht der initialWert verloren. Sie erhalten also nicht das, was von einem Standardverhalten erwartet wird .

  • Das Standardverhalten ist: Der Wert, den der Validierungsprozess annimmt, wenn das dataArgument keinen Wert für das Feld enthält.

Um dies umzusetzen, ist es einfach, Folgendes zu kombinieren initialund clean_<field>():

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 

    (...)

    def clean_tank(self):
        if not self['tank'].html_name in self.data:
            return self.fields['tank'].initial
        return self.cleaned_data['tank']
Timothé Delion
quelle