52👍
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.
17👍
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.
- [Django]-How to reset db in Django? I get a command 'reset' not found error
- [Django]-How to group by AND aggregate with Django
- [Django]-Access request in django custom template tags
8👍
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')
- [Django]-Django – Overriding the Model.create() method?
- [Django]-Create a field whose value is a calculation of other fields' values
- [Django]-Django TemplateDoesNotExist?
5👍
First, you shouldn’t have artist_id and artist fields. They are build from the model. If you need some artist name, add artist_name field, that is CharField.
Furthermore, you are trying to retrieve something from cleaned_data inside clean value. There might not be data you need – you should use values from self.data, where is data directly from POST.
- [Django]-How to update() a single model instance retrieved by get() on Django ORM?
- [Django]-Handling race condition in model.save()
- [Django]-Altering one query parameter in a url (Django)
4👍
This answer may be too late for the original poster, but I thought it might help others. I had the same problem and I did notice that self.cleaned_data(‘artist_id’) can be accessed in the clean() method, but not in the clean_artist().
When I added the extra fields in the ‘fields’ declaration of Meta, then it worked.
class Meta:
model = Music
fields=[..., 'artist_id']
You should be able to access the self.cleaned_data(‘artist_id’) in clean_artist().
- [Django]-What's the difference between staff, admin, superuser in django?
- [Django]-Specifying a mySQL ENUM in a Django model
- [Django]-How to set up a PostgreSQL database in Django
3👍
Ok I have resolved it. It seems that accessing the extra fields with cleaned_data[‘field_name’] raises a KeyError but using cleaned_data.get(‘field_name’) works. That’s weird because normal fields for the model can be accessed via cleaned_data[‘field_name’].
Update: No, it doesn’t work. With get() it doesn’t raise a KeyError but it sets a value of None because the extra fields are not in the cleaned_data dictionary.
Here is the code. In the templates there is an autocomplete, so in the form there is an “artist” field rendered as a CharField and an hidden IntegerField that will be autopopulated with the given artist id. In the clean_artist method I want to select the artist object and store it in the artist field of the form.
models.py
class Music(models.Model):
artist = models.ForeignKey(Artist, related_name='music', blank=True, null=True)
# other fields...
forms.py
class MusicForm(forms.ModelForm):
artist_id = forms.IntegerField(label="", widget=forms.HiddenInput(), required=False)
artist = forms.CharField(required=False)
# other fields ...
class Meta:
model = Music
def clean_artist(self):
if self.cleaned_data.get('artist') == '':
artist = None
else:
artist_id = self.cleaned_data.get('artist_id') # this returns always None because artist_id is not in cleaned_fields (this seemed to work with previous django versions but not with current SVN version)
if artist_id != None:
artist = Artist.objects.get(id=artist_id)
else:
artist = None
return artist
- [Django]-Django-rest-framework 3.0 create or update in nested serializer
- [Django]-Find object in list that has attribute equal to some value (that meets any condition)
- [Django]-Separation of business logic and data access in django
2👍
In Django 2 you can just add the fields as it was a normal form
class CreateCompanyForm(forms.ModelForm):
password_confirmation = forms.CharField(
label=translate('Password confirmation'),
max_length=70,
widget=forms.PasswordInput(),
required=True,
)
company_name = forms.CharField(
label="Nombre de la Compañía",
max_length=90,
widget=forms.TextInput(),
required=True,
)
class Meta:
model = AppUser
fields = (
"email",
"first_name",
"last_name",
"password",
)
- [Django]-Manage.py runserver
- [Django]-Tailwindcss: fixed/sticky footer on the bottom
- [Django]-Django: import auth user to the model
0👍
I encountered the similar problem, but in my case it appears that the extra field simply did not pass validation. And that was the reason it was not appear in form’s cleaned_data.
- [Django]-Elegant setup of Python logging in Django
- [Django]-Filter by property
- [Django]-Django Forms and Bootstrap – CSS classes and <divs>