Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ModelForm with extra fields that are not in the model

I have done a ModelForm adding some extra fields that are not in the model. I use these fields for some calcualtions when saving the form.

The extra fields appear on the form and they are sent in the POST request when uploading the form. The problem is they are not added to the cleaned_data dictionary when I validate the form. How can I access them?

like image 524
Antonio Melé Avatar asked Feb 09 '10 12:02

Antonio Melé


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 can I have multiple models in a single Django ModelForm?

In a nutshell: Make a form for each model, submit them both to template in a single <form> , using prefix keyarg and have the view handle validation. If there is dependency, just make sure you save the "parent" model before dependant, and use parent's ID for foreign key before commiting save of "child" model.

What is the difference between models and forms in Django?

The main difference between the two is that in forms that are created from forms. ModelForm , we have to declare which model will be used to create our form. In our Article Form above we have this line " model = models. Article " which basically means we are going to use Article model to create our form.

How do you make a field non editable in Django?

Every field comes in with built-in validations from Django validators. One can also add more built-in field validations for applying or removing certain constraints on a particular field. editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form.


2 Answers

EDIT 2020 (Django 2 or higher)

In Django 2+ you can add the extra fields like this:

class ProfileForm(forms.ModelForm):          extra_field = forms.ImageField()      class Meta:         model = User         fields = ['username', 'country', 'website', 'biography'] 

Original answer (Django 1)

It's possible to extend Django ModelForm with extra fields. Imagine you have a custom User model and this ModelForm:

class ProfileForm(forms.ModelForm):      class Meta:         model = User         fields = ['username', 'country', 'website', 'biography'] 

Now, imagine you want to include an extra field (not present in your User model, lets say an image avatar). Extend your form by doing this:

from django import forms  class AvatarProfileForm(ProfileForm):      profile_avatar = forms.ImageField()      class Meta(ProfileForm.Meta):         fields = ProfileForm.Meta.fields + ('profile_avatar',) 

Finally (given that the form has an ImageField), remember to include request.FILES when instantiating the form in your view:

# (view.py)  def edit_profile(request):     ...     form = AvatarProfileForm(         request.POST or None,          request.FILES or None,          instance=request.user     )     ... 

Hope it helps. Good luck!

EDIT:

I was getting a "can only concatenate tuple (not "list") to tuple" error in AvatarProfileForm.Meta.fields attribute. Changed it to a tuple and it worked.

like image 116
Cartucho Avatar answered Sep 20 '22 15:09

Cartucho


I had a very similar problem except it looked like I did all the required thing, but I was getting this error when Django was starting:

django.core.exceptions.FieldError: Unknown field(s) (my_new_field) specified for MyModel 

This was a silly mistake from me, I accidentally declared my field using a Widget class:

class MyForm(forms.ModelForm):     my_new_field = forms.HiddenInput() 

Instead of a Field class:

class MyForm(forms.ModelForm):     my_new_field = forms.CharField(widget=forms.HiddenInput()) 

Not answering the question at hand here (which is answered well already), but might help others.

like image 24
Bruno A. Avatar answered Sep 18 '22 15:09

Bruno A.