Django ModelForm with extra fields that are not in the model
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 formsclass 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.
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.
First add the field in the form
class CreateForm(forms.ModelForm):extra_field = forms.CharField(label = 'extra_field', required = False)
Now while cleaning you data, you need to retrive the extra field from self.data NOT self.cleaned_data
Correct:
self.data.get('extra_field')
Wrong:
self.cleaned_data.get('extra_field')