5

I have a custom 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 get it to recognize the argument in the code of the form ?

5 Answers 5

8

You need to set the initial value by referring to the form field instance in __init__. To get access to the form field instance in __init__, put this before the call to super:

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

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

Sign up to request clarification or add additional context in comments.

4 Comments

it doesn't know the attributes fields, is that normal ? And what if I want to later use this argument in the save method of the form ?
I goofed--the call to super needs to come before self.fields or else it won't exist yet.
Cool, this works ! And what if I want to use this varaible in the save method of the form ?
Well I guess I can pass it in a hidden field like this. It work. ANy way thanks :)
2

The thing is that my_field is initialized when the class is created, but my_arg is initialized when a new instance is created, far too late for my_field to know its value. What you can do is initialize my_field in __init__ too:

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

3 Comments

if I replace my_arg with self.my_arg in both places it appears, then it tells me it doesn't know self..
I can't get it to intialize the field in the init method. if I declare the form field in the init method, it juste doesn't show up.
@Johanna do it after the super(...) function call
0

This code is executed once at import time:

my_field = forms.CharField(initial=my_arg)

and this code is executed on form instance creation:

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

So this won't work this way. You should set initial value for the field in your __init__ method.

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

1 Comment

How would you use the initial keyword in a view ?
0

Considering your comment, I would do this:

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 the superclass and letting it do the work seems cleaner to me than directly setting it on the field instance.

1 Comment

the value I want to put as initial comes from the view calling the form, that's why I want to pass it as a parameter. And actually I don't just want to use it as an initial value but to perform a sql query in the save method
0

You simply need to pop your arg before 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, simply call

form = EpisodeCreateForm (my_arg=foo)

As an example, say you have a table of Episodes, and you want to show the availables ones in a choices menu, and select the current episode. For that, use a 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.