160 votes

Transformer un champ de formulaire Django en champ caché

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 j'essaie de garder le formulaire aussi similaire que possible. Quelle est la meilleure façon de transformer ce champ en un champ de type HiddenInput champ ?

Je sais que je peux définir des attributs sur le champ 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 façon / la plus "django" / la moins "bidouilleuse" de faire de ce champ un <input type="hidden"> champ ?

242voto

semente Points 1274

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

5 votes

C'est la meilleure réponse, à mon avis. J'ai toujours détesté utiliser le code Python de mon "contrôleur" pour déterminer l'affichage d'un champ de formulaire.

1 votes

Je fais souvent des modèles de formulaires génériques avec des crispyforms. Si vous utilisez des crispyforms ou si vous affichez des champs dans un simple forloop parce que vous voulez que la structure de votre formulaire soit dans votre classe de formulaire, le widget overriding dans le formulaire est le bon moyen de le faire. Mais si vous gérez le rendu de votre formulaire dans votre template, en effet, cette solution est beaucoup plus claire/propre.

0 votes

Il est à noter que cela semble effacer toutes les classes que vous avez appliquées au champ au préalable...

206voto

christophe31 Points 1736

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

que 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ège la méthode de sauvegarde sur le poste.

J'espère que cela vous aidera.

1 votes

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.

0 votes

Ça a l'air bizarre. Je pense que c'est lié à autre chose, est-ce que vous affichez comme HiddenInput la clé primaire des objets que vous créez ? Si oui, vous ne devriez pas.

0 votes

Cela va peut-être sans dire, mais vous devrez importer des formulaires avant que cela ne fonctionne. from django import forms

76voto

Shay Rybak Points 538

Une option qui a fonctionné pour moi, définir le champ dans le formulaire original comme :

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

alors quand vous le remplacerez dans la nouvelle classe, il gardera sa place.

51voto

rych Points 555

Tout d'abord, si vous ne voulez pas que l'utilisateur modifie les données, il semble plus propre d'exclure simplement le champ. L'inclure en tant que champ caché ne fait qu'ajouter des données supplémentaires à envoyer par câble et invite un utilisateur malveillant à les modifier alors que vous ne le souhaitez pas. Si vous avez une bonne raison d'inclure le champ mais de le cacher, vous pouvez passer un mot-clé arg au constructeur du formulaire. Quelque chose comme ceci 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.

Alors, à votre avis :

form = MyModelForm(hide_condition=True)

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

11 votes

Juste une simple astuce, kwargs.pop('hide_condition', False) au lieu de kwargs['hide_condition']. vous gérerez le cas no arg, aurez un défaut et del en même temps.

2 votes

Merci pour le tuyau, christophe31. J'ai mis à jour avec votre suggestion, car cela rend le code beaucoup plus clair.

1 votes

Est-il possible de masquer complètement le champ avec cette approche ? Par exemple, si vous définissez sur class Meta: exclude = ["fieldname"] . Le problème est que la méta-approche est "statique", alors que j'ai besoin de quelque chose de dynamique. Voir stackoverflow.com/questions/20243735/

29voto

Anjaneyulu Batta Points 2897

Pour la forme normale, vous pouvez faire

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

Si vous disposez d'un formulaire modèle, vous pouvez procéder comme suit

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

Vous pouvez également passer outre __init__ méthode

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X