Changer un champ de formulaire Django en champ masqué

128

J'ai un formulaire Django avec un RegexField, qui est très similaire à un champ de saisie de texte normal.

À mon avis, dans certaines conditions, je veux le cacher à l'utilisateur et essayer de garder le formulaire aussi similaire que possible. Quelle est la meilleure façon de transformer ce champ en HiddenInputchamp?

Je sais que je peux définir des attributs sur le terrain avec:

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

Et je peux définir la valeur initiale souhaitée avec:

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

Cependant, cela ne changera pas la forme du widget.

Quelle est la meilleure / la plus "django-y" / la moins "hacky" façon de faire de ce champ un <input type="hidden">champ?

Rory
la source

Réponses:

169

Si vous avez un modèle et une vue personnalisés, vous pouvez exclure le champ et l'utiliser {{ modelform.instance.field }}pour obtenir la valeur.

vous pouvez également préférer utiliser dans la vue:

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

mais je ne suis pas sûr que cela protégera la méthode de sauvegarde sur la poste.

J'espère que ça aide.

christophe31
la source
1
Je me retrouve avec un &quot;&quot; is not a valid value for a primary key.dans la méthode is_valid après avoir utilisé cette solution.
Jens Timmerman
Cela semble bizarre. Je pense que c'est lié à autre chose, affichez-vous comme HiddenInput la clé primaire des objets que vous créez? Si oui, vous ne devriez pas.
christophe31
Cela va peut-être sans dire, mais vous devrez importer des formulaires avant que cela ne fonctionne. from django import forms
teewuane
2
sur 1.7 utilisez cette syntaxe: hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())où la clé est la nouvelle syntaxe de widget à la fin. Ajustez pour vos besoins.
Marc
196

Cela peut également être utile: {{ form.field.as_hidden }}

semente
la source
3
C'est la meilleure réponse à mon humble avis. J'ai toujours détesté utiliser mon code Python "contrôleur" pour déterminer l'affichage d'un champ de formulaire.
trpt4him
Je crée souvent un modèle de formulaire générique avec des formes croustillantes. Si vous utilisez des formulaires croustillants ou si vous affichez des champs dans une boucle for simple parce que vous voulez que votre structure de formulaire soit dans votre classe de formulaire, le widget qui se substitue dans le formulaire est le bon moyen de le faire. Mais si vous gérez le rendu de votre formulaire dans votre modèle, en effet, cette solution est beaucoup plus claire / propre.
christophe31
Il convient de noter que cela semble effacer toutes les classes que vous avez appliquées au domaine au préalable ...
John Aaron
59

une option qui a fonctionné pour moi, définissez le champ dans le formulaire d'origine comme:

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

puis lorsque vous le remplacez dans la nouvelle classe, il conservera sa place.

Shay Rybak
la source
45

Premièrement, si vous ne voulez pas que l'utilisateur modifie les données, il semble plus simple d'exclure simplement le champ. L'inclure en tant que champ caché ajoute simplement plus de données à envoyer sur le fil et invite un utilisateur malveillant à le modifier lorsque vous ne le souhaitez pas. Si vous avez une bonne raison d'inclure le champ mais de le masquer, vous pouvez passer un mot-clé arg au constructeur du modelform. Quelque chose comme ça peut-être:

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.

Ensuite, à votre avis:

form = MyModelForm(hide_condition=True)

Je préfère cette approche à la modification des éléments internes du modèle dans la vue, mais c'est une question de goût.

rych
la source
11
juste une astuce simple, kwargs.pop ('hide_condition', False) au lieu de kwargs ['hide_condition']. vous gérerez le cas no arg, aurez une valeur par défaut et del en même temps.
christophe31
2
merci pour la pointe, christophe31. J'ai mis à jour votre suggestion, car cela rend le code beaucoup plus clair.
rych
1
Est-il possible de cacher complètement le champ avec cette approche? Comme si vous partez class Meta: exclude = ["fieldname"]. Le problème ici est que la méta-approche est "statique", mais j'ai besoin de quelque chose de dynamique. Voir stackoverflow.com/questions/20243735/…
Themerius
You cab di def __init __ (self, hide_condition = True, * args, ** kwargs) qui est le moyen le plus propre ...
Visgean Skeloru
22

Pour une forme normale, vous pouvez faire

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

Si vous avez un formulaire modèle, vous pouvez faire ce qui suit

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

Vous pouvez également remplacer la __init__méthode

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

Si vous souhaitez que le champ soit toujours masqué, utilisez ce qui suit:

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

Vous pouvez simplement utiliser css:

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

Cela rendra le champ et son étiquette invisibles.

user20310
la source