Zmień pole formularza Django na ukryte

128

Mam formularz Django z rozszerzeniem RegexField , który jest bardzo podobny do zwykłego pola wprowadzania tekstu.

Moim zdaniem pod pewnymi warunkami chcę to ukryć przed użytkownikiem i starać się, aby formularz był jak najbardziej podobny. Jaki jest najlepszy sposób, aby zamienić to pole w HiddenInputpole?

Wiem, że mogę ustawić atrybuty na polu za pomocą:

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

I mogę ustawić żądaną wartość początkową za pomocą:

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

Nie zmieni to jednak formy widżetu.

Jaki jest najlepszy / najbardziej "django-y" / najmniej "hacky" sposób na uczynienie tego pola <input type="hidden">polem?

Rory
źródło

Odpowiedzi:

169

Jeśli masz niestandardowy szablon i widok, możesz wykluczyć pole i użyć, {{ modelform.instance.field }}aby uzyskać wartość.

możesz także użyć w widoku:

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

ale nie jestem pewien, czy będzie to chronić metodę zapisywania na poście.

Mam nadzieję, że to pomoże.

christophe31
źródło
1
I w końcu z &quot;&quot; is not a valid value for a primary key.w sposobie is_valid po użyciu tego rozwiązania.
Jens Timmerman
To brzmi dziwnie. Myślę, że jest to związane z czymś innym, czy wyświetlasz jako HiddenInput klucz podstawowy obiektów, które tworzysz? Jeśli tak, nie powinieneś.
christophe31
Może to oczywiste, ale zanim to zadziała, musisz zaimportować formularze. from django import forms
teewuane
2
w wersji 1.7 użyj tej składni: hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())gdzie kluczem jest nowsza składnia widżetu na końcu. Dostosuj do swoich potrzeb.
Marc
195

Może to być również przydatne: {{ form.field.as_hidden }}

semente
źródło
3
To najlepsza odpowiedź IMHO. Zawsze nienawidziłem używania mojego „kontrolera” kodu Pythona do określania wyświetlania pola formularza.
trpt4him
Często tworzę ogólny szablon formularzy z chrupiącymi formami. Jeśli używasz CrispyForms lub wyświetlasz pola w prostej pętli forloop, ponieważ chcesz, aby struktura formularza znajdowała się w Twojej klasie formularza, widget nadpisujący w formularzu jest dobrym sposobem na zrobienie tego. Jeśli jednak zarządzasz renderowaniem formularza w swoim szablonie, to rozwiązanie jest znacznie bardziej przejrzyste / przejrzyste.
christophe 31
Warto zauważyć, że wydaje się, że usuwa to wszystkie zajęcia, które wcześniej złożyłeś w tej dziedzinie ...
John Aaron
59

opcja, która u mnie zadziałała, zdefiniuj pole w oryginalnej formie jako:

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

wtedy gdy zastąpisz go w nowej klasie, zachowa swoje miejsce.

Shay Rybak
źródło
45

Po pierwsze, jeśli nie chcesz, aby użytkownik modyfikował dane, po prostu wykluczenie pola wydaje się czystsze. Włączenie go jako ukrytego pola po prostu dodaje więcej danych do przesłania przez sieć i zachęca złośliwego użytkownika do zmodyfikowania go, gdy tego nie chcesz. Jeśli masz dobry powód, aby dołączyć pole, ale je ukryć, możesz przekazać słowo kluczowe arg do konstruktora modelu. Może coś takiego:

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.

Zatem Twoim zdaniem:

form = MyModelForm(hide_condition=True)

Wolę takie podejście do modyfikacji wewnętrznych elementów modelu w widoku, ale to kwestia gustu.

rych
źródło
11
po prostu prosta wskazówka, kwargs.pop ('hide_condition', False) zamiast kwargs ['hide_condition']. poradzisz sobie z przypadkiem braku argumentu, będziesz mieć wartość default i del w tym samym czasie.
christophe31
2
dzięki za cynk, christophe31. Zaktualizowałem twoją sugestię, ponieważ dzięki niej kod jest znacznie bardziej przejrzysty.
rych
1
Czy przy takim podejściu można całkowicie ukryć pole? Jak gdybyś zaczął class Meta: exclude = ["fieldname"]. Problem w tym, że podejście Meta jest „statyczne”, ale potrzebuję czegoś dynamicznego. Zobacz stackoverflow.com/questions/20243735/…
Themerius
You cab di def __init __ (self, hide_condition = True, * args, ** kwargs), czyli najczystszy sposób ...
Visgean Skeloru
22

W normalnej formie możesz to zrobić

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

Jeśli masz wzór, możesz wykonać następujące czynności

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

Możesz także zastąpić __init__metodę

class Myform(forms.Form):
    def __init__(self, *args, **kwargs):
        super(Myform, self).__init__(*args, **kwargs)
        self.fields['slug'].widget = forms.HiddenInput()
anjaneyulubatta505
źródło
1

Jeśli chcesz, aby pole było zawsze ukryte, użyj:

class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")
Zags
źródło
0

Możesz po prostu użyć css:

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

Spowoduje to, że pole i jego etykieta staną się niewidoczne.

user20310
źródło