Django définit les valeurs de formulaire par défaut


241

J'ai un modèle comme suit:

class TankJournal(models.Model):
    user = models.ForeignKey(User)
    tank = models.ForeignKey(TankProfile)
    ts = models.IntegerField(max_length=15)
    title = models.CharField(max_length=50)
    body = models.TextField()

J'ai également un formulaire modèle pour le modèle ci-dessus comme suit:

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput()) 

    class Meta:
        model = TankJournal
        exclude = ('user','ts')

Je veux savoir comment définir la valeur par défaut pour ce champ caché du réservoir. Voici ma fonction pour afficher / enregistrer le formulaire jusqu'à présent:

def addJournal(request, id=0):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')

    # checking if they own the tank
    from django.contrib.auth.models import User
    user = User.objects.get(pk=request.session['id'])

    if request.method == 'POST':
        form = JournalForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)

            # setting the user and ts
            from time import time
            obj.ts = int(time())
            obj.user = user

            obj.tank = TankProfile.objects.get(pk=form.cleaned_data['tank_id'])

            # saving the test
            obj.save()

    else:
        form = JournalForm()

    try:
        tank = TankProfile.objects.get(user=user, id=id)
    except TankProfile.DoesNotExist:
        return HttpResponseRedirect('/error/')

Réponses:


402

Vous pouvez utiliser l' initiale qui est expliquée ici

Vous avez deux options pour remplir la valeur lors de l'appel du constructeur de formulaire:

form = JournalForm(initial={'tank': 123})

ou définissez la valeur dans la définition du formulaire:

tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 

Et comment cette variable est-elle initialtransmise au formulaire réel? Dans le modèle de formulaire actuel, devons-nous écrire comme paramètre / argument?
mgPePe

2
@bharal C'est magique. ;-) (Ou plutôt, les constructeurs de formulaires Django comprennent la variable spéciale "initiale" et parcourent son contenu sans que vous ayez besoin de faire quoi que ce soit de plus). Personnellement, je préfère spécifier des valeurs par défaut dans la définition du formulaire et n'utiliser le mécanisme initial = ... que si la valeur par défaut souhaitée est une valeur dynamique (par exemple quelque chose entré par un utilisateur, ou basé sur son identifiant, sa situation géographique, etc.)
Richard J Foster

66
initial n'est pas par défaut. La valeur initiale ne s'applique pas si le formulaire a été lié :(.
clime

4
Commenter ici pour mentionner un autre cas d'utilisation où cette solution de paramètre initial vous aidera: lors de l'envoi d'un lien d'inscription à quelqu'un si vous souhaitez préremplir l'e-mail / id ou tout autre identifiant sur le formulaire d'inscription, alors dans ce cas, vous ne pouvez pas l'écrire dans le modèle lui-même comme dynamique, vous devez plutôt appeler le constructeur avec le paramètre initial comme mentionné par @ umnik700. Fonctionne très bien!
Keshav Agrawal

1
@Phlip: ne remplacez pas View.get_formpour définir les données initiales. Tout CBV avec un FormMixin (essentiellement tous les CBV qui créent ou modifient des données) peut soit utiliser une initialvariable au niveau de la classe (pour les valeurs par défaut immuables) ou vous pouvez remplacer FormMixin.get_initial()pour renvoyer un dict des valeurs initiales à transmettre au constructeur du formulaire (pour les valeurs par défaut dynamiques .)
GDorn

29

Autre solution: définir l'initiale après la création du formulaire:

form.fields['tank'].initial = 123

Cela fonctionne pour mon besoin, n'initiez qu'un seul champ du formulaire. Merci.
bl4ckb1rd


11

J'avais cette autre solution (je la poste au cas où quelqu'un d'autre comme moi utilise la méthode suivante du modèle):

class onlyUserIsActiveField(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(onlyUserIsActiveField, self).__init__(*args, **kwargs)
        self.fields['is_active'].initial = False

    class Meta:
        model = User
        fields = ['is_active']
        labels = {'is_active': 'Is Active'}
        widgets = {
            'is_active': forms.CheckboxInput( attrs={
                            'class':          'form-control bootstrap-switch',
                            'data-size':      'mini',
                            'data-on-color':  'success',
                            'data-on-text':   'Active',
                            'data-off-color': 'danger',
                            'data-off-text':  'Inactive',
                            'name':           'is_active',

            })
        }

L'initiale est définie sur la __init__fonction commeself.fields['is_active'].initial = False


0

J'espère que cela pourra vous aider:

form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id

0

Comme expliqué dans les documents Django , ce initialn'est pas le cas default.

  • La valeur initiale d'un champ est destinée à être affichée dans un HTML. Mais si l'utilisateur supprime cette valeur et renvoie finalement une valeur vide pour ce champ, la initialvaleur est perdue. Vous n'obtenez donc pas ce qui est attendu d'un comportement par défaut .

  • Le comportement par défaut est: la valeur que prendra le processus de validation si l' dataargument ne contient aucune valeur pour le champ.

Pour mettre en œuvre cela, un moyen simple consiste à combiner initialet clean_<field>():

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 

    (...)

    def clean_tank(self):
        if not self['tank'].html_name in self.data:
            return self.fields['tank'].initial
        return self.cleaned_data['tank']
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.