1

I'm working on a web app that has photo upload functionality. I created a ModelForm to gather minimal user info plus a photo, and when I render it in HTML as {{ form.as_p }}, the field that allows the user to upload an image shows up just fine. The problem is, the form doesn't look good.

I need to be able to manually render the form in order to make it look better. I have written the HTML for this, and everything looks right except for the ImageFileField. Only the label gets rendered, not the upload button, checkbox to clear the file, etc.

What do I need to do to get the ImageFileField from the ModelForm to render correctly in my custom HTML? I've looked at the Django docs up and down, looked here on SO and can't find anyone else who's had this issue. Many thanks in advance!

Manually rendered HTML for ModelForm

forms.py snippet

class PostForm(forms.ModelForm):

    class Meta:
        model = Items
        fields = ('title', 'description', 'image_file')

new_item.html snippet

<form enctype="multipart/form-data" method="post" action="" class="post-form">

    {% csrf_token %}

    {{ form.non_field_errors }}

    <div class="fieldWrapper">
        {{ form.title.errors }}
        <label for="{{ form.title.id_for_label }}">Title:</label><br>
        {{ form.title }}
    </div><br>

    <div class="fieldWrapper">
        {{ form.description.errors }}
        <label for="{{ form.description.id_for_label }}">Description:    </label><br>
        {{ form.description }}
    </div><br>

    <div class="fieldWrapper">
        {{ form.image_field.errors }}
        <label for="{{ form.image_field.id_for_label }}">Image (optional):</label><br>
        {{ form.image_field }}
    </div>

    <button type="submit" class="save btn btn-default">Save</button>

</form>

models.py snippet

class Items(models.Model):

    title = models.CharField(max_length=1000, null=False)
    description = models.TextField(max_length=1000, null=False)
    image_file = models.ImageField(max_length=1000,
                                   blank=True,
                                   default='',
                                   null=True,
                                   upload_to='item_photos')
allardbrain
  • 599
  • 1
  • 7
  • 14
  • Show your model please – e4c5 Jun 16 '16 at 04:09
  • @e4c5 I added a snippet from my models.py. – allardbrain Jun 16 '16 at 17:01
  • @solarissmoke In researching this problem, I of course read through the SO question you've linked to as a possible duplicate. The difference between our posts is that my ImageFileField simply doesn't show up in the rendering of the form in HTML, whereas the other person wants to customize an ImageFileField that already shows up. I'm seeking help with how to get my ImageFileField to render. Thanks! – allardbrain Jun 16 '16 at 17:01

2 Answers2

1

By default django ModelForm uses django.forms.ImageField and not ClearableInputField for django.db.ImageField as revealed at https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/#field-types

And I do believe you actually meant ClearableFileInput

ClearableFileInput¶ class ClearableFileInput File upload input: , with an additional checkbox input to clear the field’s value, if the field is not required and has initial data.

How you can make use of it is by changing the widget in the class meta

class PostForm(forms.ModelForm):

    class Meta:
        model = Items
        fields = ('title', 'description', 'image_file')
        widgets = {
            'name': ClearableFileInput(),
        }
e4c5
  • 52,766
  • 11
  • 101
  • 134
  • Thank you, @e4c5, you are correct. I got the field type mixed up. I ended up referencing the HTML source code for a solution. I appreciate your help with this! – allardbrain Jun 17 '16 at 01:15
  • Thanks, @e4c5, I just upvoted your answer. I'm unable to "accept" the answer I provided until tomorrow, per the error message. – allardbrain Jun 17 '16 at 01:26
1

I ended up using the Chrome tool to inspect the HTML source for the page that rendered correctly (but ugly), and used that as a guide to custom build the form in HTML to my liking. This is what I needed to add into my HTML form to get it right:

            {% if item.image_file %}
            Currently:
            <a href="{{item.image_file.url}}"> {{item.image_file.url}}</a>
            <input id="image_file-clear_id" name="image_file-clear" type="checkbox" /> <label for="image_file-clear_id">Clear</label><br />Change: <input id="id_image_file" name="image_file" type="file" /></p>
            {% endif %}

            {% if not item.image_file %}
            <input id="id_image_file" name="image_file" type="file" /></p>
            {% endif %}
allardbrain
  • 599
  • 1
  • 7
  • 14