Adding an extra field in a forms.ModelForm

Question:

I am trying to create a modelForm in django, however when i try to add an extra field, i get a field error:

django.core.exceptions.FieldError: Unknown field(s) (select_file_path) specified for ProjectFile

My form is as follows:

class ProjectFileForm(forms.ModelForm):
    select_file_path = forms.Select()
    class Meta:
        model = ProjectFile
        fields = ["project", "form_type", "select_file_path", "file_name", "full_file_path", "author"]
        widgets = {"author": HiddenInput()}
    field_order = ["project", "form_type", "select_file_path", "file_name", "full_file_path"]

Not too sure whats going wrong here as a model form is defined the same way in the docs:
https://docs.djangoproject.com/en/4.1/topics/forms/modelforms/#overriding-the-default-fields

Asked By: lee King

||

Answers:

you could just manually render the <input> inside the <form> in the template. It will automatically post with the usual form data and then you handle it in the view (this is the simple way of going this, butttt extra template stuff)
I could write up a little example if you want this way, just let me know if you’re using class based view or normal ones (if class based give me some example code cause I don’t use class based views

You can’t put fields not in the model inside of a form.ModelForm.

  • you just can’t put it in the META (who knew)

You could do a form.Form, but you’ve got to handle the saving + unique field validation

class customForm(forms.Form):
    desc    = forms.CharField()
    color   = forms.CharField()

    def __init__(self,  *args, **kwargs):
        self.instance =  kwargs.pop('instance') if 'instance' in kwargs else None

        super(customForm, self).__init__(*args, **kwargs)
        self.fields['desc'].widget.attrs={'maxlength': '200'}
        self.fields['color'].widget.attrs={'maxlength': '50'}


    def is_valid(self):
        valid = super(customForm, self).is_valid()
        if self.cleaned_data.get('desc') == 'Nealium is Dumb':
            self.add_error('desc', 'Slander is not Allowed')
            valid = False
        return valid

    def save(self):
        if self.obj:
            # exists / update
            self.instance.desc = self.cleaned_data.get('desc')
            self.instance.save()
        else:
            # new / create
            mymodel.create(desc=self.cleaned_data.get('desc'))

        # dothing something with color
        self.cleaned_data.get('desc')
Answered By: Nealium

Remove select_file_path from the fields of Meta class, as only the models’ fields can be included in this attribute.

As mentioned by @Ian, the forms.Select() field is a widget and is not able to be rendered inside of a template in that manner, in this particular case, simply change:

select_file_path = forms.select()

To a form field rather then a widget, e.g.

select_file_path = forms.ChoiceField()
Answered By: liam
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.