Pass parameter for form in Django

I have a user form to which I would like to pass a parameter. Following this example, I came up with the following code:

class EpisodeCreateForm(forms.Form): def __init__(self, *args, **kwargs): my_arg = kwargs.pop('my_arg') super(EpisodeCreateForm, self).__init__(*args, **kwargs) my_field = forms.CharField(initial=my_arg) 

But I get the following error:

 Exception Value: name 'my_arg' is not defined 

How can I make it recognize an argument in form code?

+4
source share
5 answers

You need to set the initial value by accessing the instance of the form field in __init__ . To access an instance of a form field in __init__ , put this before calling super :

 self.fields['my_field'].initial=my_arg 

And remove initial=my_arg , from where you declare my_field , because at that moment (when the class is declared) my_arg not in the scope.

+7
source

The fact is that my_field initialized when the class is created, but my_arg initialized when the new instance is created, it's too late for my_field to know its value. What you can do is initialize my_field to __init__ :

 def __init__(self, *args, **kwargs): my_arg = kwargs.pop('my_arg') super(EpisodeCreateForm, self).__init__(*args, **kwargs) if not self.my_field: self.my_field = my_arg 
+1
source

This code is executed once during import:

 my_field = forms.CharField(initial=my_arg) 

and this code is executed when the form is instantiated:

 my_arg = kwargs.pop('my_arg') super(EpisodeCreateForm, self).__init__(*args, **kwargs) 

So this will not work. You must set the initial value for the field in your __init__ method.

By the way, all this seems unnecessary, why not use the 'initial' keyword in the view?

0
source

Given your comment, I would do the following:

 class EpisodeCreateForm(forms.Form): def __init__(self, *args, **kwargs): self.my_arg = kwargs.pop('my_arg') kwargs.setdefault('initial', {})['my_field'] = self.my_arg super(EpisodeCreateForm, self).__init__(*args, **kwargs) def save(self): do_something(self.my_arg) ... super(EpisodeCreateForm, self).save() my_field = forms.CharField() 

Passing initial to a superclass and letting it do the job seems cleaner to me than setting it directly in a field instance.

0
source

You just need to set your argument to super() and put it in the fields dictionnary after super() :

 class EpisodeCreateForm(forms.Form): my_field = forms.CharField(label='My field:') def __init__(self, *args, **kwargs): my_arg = kwargs.pop('my_arg') super(EpisodeCreateForm, self).__init__(*args, **kwargs) self.fields['my_arg'].initial = my_arg 

Then just call

 form = EpisodeCreateForm (my_arg=foo) 

As an example, let's say that you have a table of episodes, and you want to show available in the selection menu and select the current episode. To do this, use ModelChoiceField :

 class EpisodeCreateForm(forms.Form): available_episode_list = Episode.objects.filter(available=True) my_field = forms.ModelChoiceField(label='My field:', queryset=available_episode_list) def __init__(self, *args, **kwargs): cur_ep = kwargs.pop('current_episode') super(EpisodeCreateForm, self).__init__(*args, **kwargs) self.fields['current_episode'].initial = cur_ep 
0
source

All Articles