Ändern Sie ein Django-Formularfeld in ein verstecktes Feld

128

Ich habe ein Django-Formular mit einem RegexField, das einem normalen Texteingabefeld sehr ähnlich ist.

Meiner Ansicht nach möchte ich es unter bestimmten Bedingungen vor dem Benutzer verbergen und versuchen, das Formular so ähnlich wie möglich zu halten. Was ist der beste Weg, um dieses Feld in ein HiddenInputFeld zu verwandeln ?

Ich weiß, dass ich Attribute auf dem Feld festlegen kann mit:

form['fieldname'].field.widget.attr['readonly'] = 'readonly'

Und ich kann den gewünschten Anfangswert einstellen mit:

form.initial['fieldname'] = 'mydesiredvalue'

Dies ändert jedoch nichts an der Form des Widgets.

Was ist der beste / am meisten "django-y" / am wenigsten "hackige" Weg, um dieses Feld zu einem <input type="hidden">Feld zu machen ?

Rory
quelle

Antworten:

169

Wenn Sie eine benutzerdefinierte Vorlage und Ansicht haben, können Sie das Feld ausschließen und verwenden {{ modelform.instance.field }}, um den Wert abzurufen.

Sie können es auch vorziehen, in der Ansicht zu verwenden:

form.fields['field_name'].widget = forms.HiddenInput()

Ich bin mir jedoch nicht sicher, ob dies die Speichermethode auf dem Postweg schützt.

Ich hoffe es hilft.

christophe31
quelle
1
&quot;&quot; is not a valid value for a primary key.Nach Verwendung dieser Lösung erhalte ich eine Methode in der is_valid-Methode.
Jens Timmerman
Es klingt komisch. Ich denke, es hängt mit etwas anderem zusammen. Zeigen Sie den Primärschlüssel der von Ihnen erstellten Objekte als HiddenInput an? Wenn ja, sollten Sie nicht.
Christophe31
Vielleicht ist dies selbstverständlich, aber Sie müssen Formulare importieren, bevor dies funktioniert. from django import forms
Teewuane
2
Verwenden Sie unter 1.7 diese Syntax: hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())wobei der Schlüssel am Ende die neuere Widget-Syntax ist. Optimieren Sie für Ihre Bedürfnisse.
Marc
195

Dies kann auch nützlich sein: {{ form.field.as_hidden }}

semente
quelle
3
Dies ist meiner Meinung nach die beste Antwort. Ich habe es immer gehasst, meinen Python-Code "Controller" zu verwenden, um die Anzeige eines Formularfelds zu bestimmen.
trpt4him
Ich mache oft generische Formularvorlagen mit knusprigen Formen. Wenn Sie knusprige Formulare verwenden oder Felder in einer einfachen Forloop anzeigen, weil Sie Ihre Formularstruktur in Ihrer Formularklasse haben möchten, ist das im Formular überschreibende Widget der gute Weg, dies zu tun. Wenn Sie Ihr Formular-Rendering in Ihrer Vorlage verwalten, ist diese Lösung in der Tat viel klarer / sauberer.
Christophe31
Es ist erwähnenswert, dass dies alle Klassen zu löschen scheint, die Sie zuvor auf das Feld angewendet haben ...
John Aaron
59

Eine Option, die für mich funktioniert hat. Definieren Sie das Feld im Originalformular wie folgt:

forms.CharField(widget = forms.HiddenInput(), required = False)

Wenn Sie es dann in der neuen Klasse überschreiben, behält es seinen Platz.

Shay Rybak
quelle
45

Erstens, wenn Sie nicht möchten, dass der Benutzer die Daten ändert, erscheint es sauberer, das Feld einfach auszuschließen. Wenn Sie es als verstecktes Feld einfügen, werden einfach mehr Daten hinzugefügt, die über das Netzwerk gesendet werden sollen, und ein böswilliger Benutzer wird aufgefordert, diese zu ändern, wenn Sie dies nicht möchten. Wenn Sie einen guten Grund haben, das Feld einzuschließen, es aber auszublenden, können Sie dem Konstruktor der Modellform ein Schlüsselwort arg übergeben. So etwas vielleicht:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
    def __init__(self, *args, **kwargs):
        from django.forms.widgets import HiddenInput
        hide_condition = kwargs.pop('hide_condition',None)
        super(MyModelForm, self).__init__(*args, **kwargs)
        if hide_condition:
            self.fields['fieldname'].widget = HiddenInput()
            # or alternately:  del self.fields['fieldname']  to remove it from the form altogether.

Dann aus Ihrer Sicht:

form = MyModelForm(hide_condition=True)

Ich bevorzuge diesen Ansatz, um die Interna der Modellform in der Ansicht zu ändern, aber es ist Geschmackssache.

Rych
quelle
11
Nur ein einfacher Tipp: kwargs.pop ('hide_condition', False) anstelle von kwargs ['hide_condition']. Sie werden den Fall no arg behandeln, einen Standard haben und gleichzeitig löschen.
Christophe31
2
danke für den tipp, christophe31. Ich habe mit Ihrem Vorschlag aktualisiert, da dies den Code viel klarer macht.
Rych
1
Ist es mit diesem Ansatz möglich, das Feld vollständig auszublenden? Als ob du dich anlegst class Meta: exclude = ["fieldname"]. Das Problem hierbei ist, dass der Meta-Ansatz "statisch" ist, aber ich brauche etwas Dynamisches. Siehe stackoverflow.com/questions/20243735/…
Themerius
Sie können __init __ (self, hide_condition = True, * args, ** kwargs) definieren, was der sauberste Weg ist ...
Visgean Skeloru
22

Für normale Form können Sie tun

class MyModelForm(forms.ModelForm):
    slug = forms.CharField(widget=forms.HiddenInput())

Wenn Sie ein Modellformular haben, können Sie Folgendes tun

class MyModelForm(forms.ModelForm):
    class Meta:
        model = TagStatus
        fields = ('slug', 'ext')
        widgets = {'slug': forms.HiddenInput()}

Sie können die __init__Methode auch überschreiben

class Myform(forms.Form):
    def __init__(self, *args, **kwargs):
        super(Myform, self).__init__(*args, **kwargs)
        self.fields['slug'].widget = forms.HiddenInput()
anjaneyulubatta505
quelle
1

Wenn das Feld immer ausgeblendet werden soll, verwenden Sie Folgendes:

class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")
Zags
quelle
0

Sie können einfach CSS verwenden:

#id_fieldname, label[for="id_fieldname"] {
  position: absolute;
  display: none
}

Dadurch werden das Feld und seine Beschriftung unsichtbar.

user20310
quelle