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?

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.


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 }}


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.


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.


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()

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")

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.