Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Assign default value to field in ModelForm

Tags:

python

django

In my application I have a CreateView that must initialize some fields of the model with a default value, different from the default defined inside the model.

I do not want the user to edit the value, thus I put the field in the exclude list

class AForm(ModelForm):
    class Meta:
        model = AModel
        exclude = ['a_field']

class AView(CreateView):
    form_class = AForm

The question is: where do I set the value of a_field?

I tried to define clean methods inside AForm, like thus

class AForm(ModelForm):
    [...]
    def clean(self):
        d = super(AForm, self).clean()
        d['a_field'] = 10
        return d

however a_field is set to whatever its default value defined in the model is, rather than 10. I also tried defining clean_a_field, but that is simply not executed.

If I remove a_field from the exclude list, then the clean and clean_a_field will work, but the form won't validate unless I render some <input name="a_field"> inside the template, which is not optimal.

like image 398
Luca De Feo Avatar asked May 18 '14 04:05

Luca De Feo


2 Answers

I managed to solve the issue in a way that makes me satisfied, although I'm still not 100% happy with the code.

a_field is a required (by the model) field, thus it is necessary to render an <input name="a_field"> inside the template. The trick was to make a_field non-required:

class AForm(ModelForm):
    a_field = Field(required=False, 
                    widget=forms.HiddenInput)
    class Meta:
        model = AModel

    def clean_a_field(self):
        return 10

This way I can avoid rendering the field in my template, and the form will still validate. And even if the form is rendered with {{ form.as_p }}, widget=forms.HiddenInput saves my day.

like image 59
Luca De Feo Avatar answered Oct 23 '22 19:10

Luca De Feo


Exclude the field from the form, then in the view you can set the value before you save the form:

form = AForm(request.POST)
if form.is_valid():
    new_record = form.save(commit=False)
    new_record.a_field = 10
    new_record.save()

You also might want to avoid the exclude list and specify which fields you'd like to include with the fields attr of the form definition. See the first paragraph here in the docs.

like image 4
Joel Bartlett Avatar answered Oct 23 '22 19:10

Joel Bartlett