Decent image loader widget in django

I’m working on a website where I need to be able to load an image. The default widget is abysmal; it has a url to the current image, a checkbox and a file loader input element. Even styled, it looks pretty bad. So, I’ve taken upon myself to prettify it and get from this:

Default widget
Default widget

to this:

Styled widget
Styled widget

To accomplish the transformation, we need:

After copying the various resources around (e.g. the bootstrap-filestyle in static), we need to create a custom widget for the file input.

and use it in our form:

Now, when the form will be rendered, it’ll use the ImageThumbnailFileInput widget.

The next step is to create the HTML template used in the widget. Following the hints from floppy-forms’ examples, I ended up with something like this:

The code contains an easy_thumbnails reference for image display. You can replace it with e.g. a simple ImageField. Otherwise, it is pretty self-explanatory:

  • There’s a label part of the widget (used by crispy forms to format it nicely)
  • There’s an {% if %} for the case where there’s an image already vs. not (and using a placeholder)
  • A checkbox to clear the image (just like the original widget)
  • A file selector input, styled via bootstrap-filestyle

If you just use it, you’ll find that the read-only field associated with the file input is either unstyled or fills up 100% of the width. The 100% part is the way the .form-control class is defined in bootstrap 3. To fix that, I’ve added a custom class in my customiser style file:

HTH,

Update 1: Thanks to John D. for pointing out my missing reference to easy_thumbnails.


A little experiment: If you find this post and ad below useful, please check the ad out :-)




16 thoughts on “Decent image loader widget in django

  1. What thumbnail package are you using? I am getting errors on {% load thumbnail %} in the template.

    1. Been scratching my head for a cuolpe of hours trying to figure out why this was happening when my template file was identical. Added your code to my child functions.php file and it has worked a treat! Thanks!

  2. Hi, iam used blog for my site but can’t get image
    i am using in models.py

    pro_image1 = models.ImageField(upload_to=’products/’,blank=True, null=True, verbose_name = _(‘Product Image1′)),
    pro_image2 = models.ImageField(upload_to=’products/’,blank=True, null=True, verbose_name = _(‘Product Image2′)),
    pro_image3 = models.ImageField(upload_to=’products/’,blank=True, null=True, verbose_name = _(‘Product Image3′)),
    pro_image4 = models.ImageField(upload_to=’products/’,blank=True, null=True, verbose_name = _(‘Product Image4’)),

    and my forms.py

    from floppyforms import ClearableFileInput
    import floppyforms as forms

    class ImageThumbnailFileInput(forms.ClearableFileInput):
    template_name = ‘floppyforms/image_thumbnail.html’

    class ProductForm(TranslatableModelForm):
    class Meta:
    model = Product
    fields = (‘product_name’,’category’,’pro_image1′,’pro_image2′,’pro_image3′,’pro_image4′,’price’,’negotiable’,’des’,’dis_code’)
    widgets = {‘pro_image1’: ImageThumbnailFileInput,
    ‘pro_image2’: ImageThumbnailFileInput,
    ‘pro_image3’: ImageThumbnailFileInput,
    ‘pro_image4’: ImageThumbnailFileInput,
    }

    but i can’t get image in form in html
    it shows empty box written “600×250”
    how can i solve this
    Pls help!!
    thanks in advance!!!

    1. Hmm. It’s odd. Here are some possible pointers:

      • Is the image saved and uploaded? In some cases, the upload may look like it’s working, but the image is not saved on the server side and no errors are provided. I had that when I was missing configs on AWS.
      • You may need to tweak the template to match your code…

      Let me know if the above don’t give you any results and I’ll see what I can do :)

  3. Actually i don’t follow your template since the (default) crispy templates will ultimately render the field itself using the specified widget; in your case the widget is customized using floppyforms. So your template should be a lot simpler, right?

  4. Thanks for the guide! What are the chances you might try to add the ability to accept a URL in addition to a File Upload as the source of an image? =)

  5. Hi,
    I am trying to used this example. I want to used in a FormSet with crispy form and rendering with management_form.

    I can show what I want, the problem comes at the moment I try to save. I got a message that say that there isn’t any image, in records that I not focused, when I editing or creating another record.

    What should I do?
    Thanks

    {% extends ‘admin_dramor/modelos/base/base_admin.html’ %}
    {% load crispy_forms_tags %}

    {% block title %}Editar Fotos Perfil{% endblock %}

    {% block content %}

    {% endblock %}

  6. Modern Django renders all its fields via templates now; Floppy is no longer required. You could drop the dependency and import and just override django.forms.widgets.ClearableFileInput.

    The rest would be the same, I think.

    1. And for what it’s worth, please put dates on articles and comments! I just noticed comments from “May 26” (the future for me) which actually mean “May 26 2017”. Finally got the article date from your RSS feed :\

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to top