45

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
1
  • 1
    My problem was I was calling super.__init after setting self.initial... Sheesh!
    – MagicLAMP
    Commented Sep 7, 2017 at 6:15

6 Answers 6

43

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
0
24

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
6
  • 2
    @ndpu - thanks, but that too doesn't work - the field object exists, and it has a data attribute of "initial" that is indeed set to the initial value, but it's not showing up on the form. @karthikr - the code that establishes the form fields is executed AFTER the super() call, and it isn't until this code executes that I know what the initial values(s) should be. I also tried `self.initial.update({field_name: field_value})' but that also leaves the field blank on the page. I also tried to set the initial field argument as part of the field definition - no success with that approach. Commented Mar 14, 2014 at 16:38
  • 2
    Well. i use the exact same code as I have shown in the answer, and it works for me.
    – karthikr
    Commented Mar 14, 2014 at 21:31
  • @karthikr - My guess is that yours is working because you're calling super() after setting the property. Things got even more interesting in playing with this on Friday - not only can I verify that the initial value exists, it's also a required field, and the value's presence is causing the form to pass is_valid() in the view's post() method! So, I'm getting the worst of everything - the value is there and is validated, but won't display on the form!! Commented Mar 17, 2014 at 14:23
  • I'm no closer to getting this working the way I need it to do so, but I'm making a couple of discoveries, and the failure may not lie with how I'm populating the initial value, but with the behavior of the field type (or my understanding of that behavior). I'm going to post a new topic that gets into this aspect of the issue. Thanks for all your input. Commented Mar 17, 2014 at 16:35
  • you have to init the form with super first to make self.fields available
    – biodiv
    Commented Jun 6, 2016 at 8:18
9

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'
0

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)
0

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',
    )
0

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.