Steve Sawyer
Steve Sawyer

Reputation: 1885

Setting initial Django form field value in the __init__ method

Django 1.6

I have a working block of code in a Django form class as shown below. The data set from which I'm building the form field list can include an initial value for any of the fields, and I'm having no success in setting that initial value in the form. The if field_value: block below does indeed populate the initial form dictionary attribute, but the initial value is not being displayed. Note that (in case you are wondering) the .initial attribute does not exist until after the super() call.

Can this be done?

If so, what I'm not doing right to make this work?

Thanks!

def __init__(self, *args, **kwargs):
    id = kwargs.pop('values_id', 0)
    super(LaunchForm, self).__init__(*args, **kwargs)
    # Lotsa code here that uses the id value
    # to execute a query and build the form
    # fields and their attributes from the 
    # result set

    if field_value:
        self.initial[field_name] = field_value

Upvotes: 45

Views: 62381

Answers (6)

Hehe
Hehe

Reputation: 1

Make initial= "" in the field definition will solve your problem. Both proposed methods are correct you need just to define initial= "" in the field definitoion and the problem is solved

Upvotes: 0

Megan Word
Megan Word

Reputation: 2131

I want to mention, although this might not solve your problem, that an 'initial' dict kwarg sent to a form appears to get preference over field['field_name'].initial.

class MyView(View):
    form = MyForm(initial={'my_field': 'first_value'})

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['my_field'].initial = 'second_value'

my_field rendered will have initial set to 'first_value'.

Some options (among others) might be:

Determine second_value in the view before initializing the form:

class MyView(View):
    # determine second_value here
    form = MyForm(initial={'my_field': 'second_value'})

replace first_value with second_value in initial before calling super():

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        # determine second_value here
        if kwargs.get('initial', None):
            kwargs['initial']['my_field'] = 'second_value'
        super().__init__(*args, **kwargs)

Make sure 'first_value' isn't in kwargs['initial'] before calling super():

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        if kwargs.get('initial', None):
            if kwargs['initial']['my_field']
                del(kwargs['initial']['my_field']
        super().__init__(*args, **kwargs)
        # determine second_value here
        self.fields['my_field'].initial = 'second_value'

Upvotes: 9

Julio Marins
Julio Marins

Reputation: 10639

This works:

class BarForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['state'] = forms.ChoiceField(
            required=False,
            choices=Foo.ADDRESS_STATE_CHOICES,
            disabled='disabled',
            initial='xyz',
        )

    state = forms.ChoiceField(
        label='State',
        choices=Foo.ADDRESS_STATE_CHOICES,
        initial='foo',
    )

Upvotes: 0

ndpu
ndpu

Reputation: 22561

Try this way:

super(ViagemForm, self).__init__(*args, **kwargs)

if field_value:
    #self.initial[field_name] = field_value
    self.fields[field_name].initial = field_value

Upvotes: 24

Jim
Jim

Reputation: 14270

I had a similar problem setting the initial value for a radio button called 'needs_response' and solved it by inspecting self's attributes and referencing 'declared_fields':

    # views.py
    def review_feedback_or_question(request, template, *args, **kwargs):
        if 'fqid' in kwargs:
            fqid = kwargs['fqid']
        submission = FeedbackQuestion.objects.get(pk=fqid)
        form = FeedbackQuestionResponseForm(submission_type=submission.submission_type)
        # other stuff

    # forms.py
    class FeedbackQuestionResponseForm(forms.Form):
        CHOICES = (('1', 'Yes'), ('2', 'No'))
        response_text = forms.CharField(
            required=False,
            label='',
            widget=forms.Textarea(attrs={'placeholder': 'Enter response...'}))
        needs_response = forms.ChoiceField(choices=CHOICES,
            label='Needs response?',
            widget=forms.RadioSelect())
        def __init__(self, *args, **kwargs):
            if 'submission_type' in kwargs:
                submission_type = kwargs.pop('submission_type')
                if submission_type == 'question':
                    self.declared_fields['needs_response'].initial = 1
                else:
                    self.declared_fields['needs_response'].initial = 2
            super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)

Upvotes: 0

I had that exact same problem and I solved it doing this:

def __init__(self, *args, **kwargs):
    instance = kwargs.get('instance', None)

    kwargs.update(initial={
        # 'field': 'value'
        'km_partida': '1020'
    })

    super(ViagemForm, self).__init__(*args, **kwargs)

    # all other stuff

Upvotes: 43

Related Questions