Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set initial values for a ModelForm when instance is also given

It seems like if a ModelForm is given an instance, it ignores any values you provide for initial and instead sets it to the value of the instance -- even if that instance is an empty model record.

Is there any way to create a form with an instance and have it set initial data?

I need it because I'm saving related records and they don't appear to save correctly unless the ModelForm is given an instance when created.

I'm sure the answer to this is straightforward and I'm just missing something obvious.

Here is the relevant code:

in the view:

form = form_class(person=person, conference=conference, initial=initial, instance=registration)

where form_class is RegistrationForm and then in the registration form:

class RegisterForm(forms.ModelForm):
    ... fields here ...

    def __init__(self, *args, **kwargs):
        ... other code ...
        self.person = kwargs.pop('person')
        super(RegisterForm, self).__init__(*args, **kwargs)
        for key, in self.fields.keys():
            if hasattr(self.person, key):
                self.fields[k].initial = getattr(self.person, key)

Then when I call the field, the related fields are empty.

like image 356
Jordan Reiter Avatar asked Aug 15 '13 14:08

Jordan Reiter


People also ask

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.

How do you customize a form in Django?

So, we have to just design the HTML with css, and use it in Django by just replacing the input tag with render_field and form. field_name with {% %} at the end and design it with our choice.

How can we make field required in Django?

Let's try to use required via Django Web application we created, visit http://localhost:8000/ and try to input the value based on option or validation applied on the Field. Hit submit. Hence Field is accepting the form even without any data in the geeks_field. This makes required=False implemented successfully.

What is forms ModelForm in Django?

Django Model Form It is a class which is used to create an HTML form by using the Model. It is an efficient way to create a form without writing HTML code. Django automatically does it for us to reduce the application development time.


1 Answers

Figured this out after a little bit of googling.

You have to set the initial value before calling super.

So instead of looping through self.fields.keys(), I had to type out the list of fields that I wanted and looped through that instead:

class RegisterForm(forms.ModelForm):
    ... fields here ...
    initial_fields = ['first_name', 'last_name', ... ]

    def __init__(self, *args, **kwargs):
        ... other code ...
        self.person = kwargs.pop('person')
        for key in self.initial_fields:
            if hasattr(self.person, key):
                self.fields[k].initial = getattr(self.person, key)
        super(RegisterForm, self).__init__(*args, **kwargs)

@Daria rightly points out that you don't have self.fields before calling super. I'm pretty sure this will work:

class RegisterForm(forms.ModelForm):
    ... fields here ...
    initial_fields = ['first_name', 'last_name', ... ]

    def __init__(self, *args, **kwargs):
        ... other code ...
        initial = kwargs.pop('initial', {})
        self.person = kwargs.pop('person')
        for key in self.initial_fields:
            if hasattr(self.person, key):
                initial[key] = initial.get(key) or getattr(self.person, key)
        kwargs['initial'] = initial
        super(RegisterForm, self).__init__(*args, **kwargs)

In this version, we use the initial argument to pass the values in. It's also written so that if we already have a value in initial for that field, we don't overwrite it.

like image 119
Jordan Reiter Avatar answered Sep 28 '22 03:09

Jordan Reiter