Alterar um campo de formulário do Django para um campo oculto

128

Eu tenho um formulário Django com a RegexField, que é muito semelhante a um campo de entrada de texto normal.

Na minha opinião, sob certas condições, quero ocultá-lo do usuário e tentar manter o formulário o mais semelhante possível. Qual é a melhor maneira de transformar esse campo em um HiddenInputcampo?

Eu sei que posso definir atributos no campo com:

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

E eu posso definir o valor inicial desejado com:

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

No entanto, isso não muda a forma do widget.

Qual é a melhor / mais "django-y" / menos "hacky" maneira de tornar esse campo um <input type="hidden">campo?

Rory
fonte

Respostas:

169

Se você tiver um modelo e uma exibição personalizados, poderá excluir o campo e usar {{ modelform.instance.field }}para obter o valor.

você também pode preferir usar na exibição:

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

mas não tenho certeza se ele protegerá o método save na postagem.

Espero que ajude.

christophe31
fonte
1
&quot;&quot; is not a valid value for a primary key.Acabo com um no método is_valid depois de usar esta solução.
Jens Timmerman
Parece estranho. Eu acho que está relacionado a outra coisa, você está exibindo como HiddenInput a chave primária dos objetos que está criando? Se sim, você não deveria.
christophe31
Talvez isso seja óbvio, mas você precisará importar formulários antes que isso funcione. from django import forms
Julio
2
no 1.7, use esta sintaxe: hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())onde a chave é a sintaxe mais recente do widget no final. Ajustar para suas necessidades.
Marc
195

Isso também pode ser útil: {{ form.field.as_hidden }}

semente
fonte
3
Esta é a melhor resposta IMHO. Eu sempre odiei usar meu código Python "controller" para determinar a exibição de um campo de formulário.
trpt4him
Costumo criar modelos de formulários genéricos com crispyforms. Se você usa crispyforms ou exibe campos em um forloop simples, porque deseja que sua estrutura de formulários em sua classe de formulários, o widget que substitui o formulário é a melhor maneira de fazê-lo. Mas se você gerencia a renderização do formulário no seu modelo, essa solução é muito mais clara / limpa.
christophe31
Vale a pena notar que isso parece apagar todas as classes que você aplicou anteriormente ao campo ...
John Aaron
59

uma opção que funcionou para mim, defina o campo na forma original como:

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

quando você substituí-lo na nova classe, ele manterá seu lugar.

Shay Rybak
fonte
45

Em primeiro lugar, se você não deseja que o usuário modifique os dados, parece mais limpo simplesmente excluir o campo. Incluí-lo como um campo oculto apenas adiciona mais dados para enviar por fio e convida um usuário mal-intencionado a modificá-lo quando você não deseja. Se você tiver um bom motivo para incluir o campo, mas ocultá-lo, poderá passar uma palavra-chave arg para o construtor do modelform. Algo assim talvez:

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.

Então, na sua opinião:

form = MyModelForm(hide_condition=True)

Prefiro essa abordagem a modificar as partes internas do modelform na visualização, mas é uma questão de gosto.

rych
fonte
11
apenas uma dica simples, kwargs.pop ('hide_condition', False) em vez de kwargs ['hide_condition']. você lidará com o caso no arg, terá um padrão e del ao mesmo tempo.
precisa
2
obrigado pela dica, christophe31. Atualizei sua sugestão, pois isso torna o código muito mais claro.
R16 de
1
É possível ocultar completamente o campo com essa abordagem? Como se você ativar class Meta: exclude = ["fieldname"]. O problema aqui é que a meta-abordagem é "estática", mas preciso de algo dinâmico. Veja stackoverflow.com/questions/20243735/…
Themerius
Você táxi di def __init __ (self, hide_condition = True, * args, ** kwargs), que é a forma mais limpa ...
Visgean Skeloru
22

Para a forma normal, você pode fazer

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

Se você possui um modelo, pode fazer o seguinte

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

Você também pode substituir o __init__método

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

Se você deseja que o campo esteja sempre oculto, use o seguinte:

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

Você pode apenas usar css:

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

Isso tornará o campo e seu rótulo invisíveis.

user20310
fonte