Upload Multiple Images to a Model with Django

Juli Colombo
Aug 20, 2020 · 5 min read

Get flexibility without having several image fields

Very often in projects, especially in ecommerces, the client wants to link an image to a product. Way too much time has passed by for me to learn that most of the time the requirement changes in the middle of the project: the client has to be able to upload more than one image to a merchandise. And not only that, the amount of images is variable depending on the product.

Sometimes the first reaction is to panic, but I’ve come to a solution that is pretty flexible and easy to implement. So if you are in the same situation, I beg you to stay calm and read this article, it may help you!

The problem

To associate an image to a model in Django, we need to define an ImageField in the corresponding model, setting some optional configurations:

If we want to upload multiple images to a model this way, we just need to define as many fields as we need:

This solution is fine if:

  • We know how many images we have
  • We need to access them by name, for instance: model.image_two

As we mentioned before, in ecommerces very often, we need a product gallery to show all the images referring to a product, and the amount of images and their names vary from one product to another, looking in the frontend something like this:

With the approach we made before, it’s unlikely that we can build a flexible design to reach the final goal.

The Image model

To be able to add several images to one product, we will need to have an intermediate model, we will call it Image from now on, which has the actual image file attached. The product model will have a reference to several Image objects.

I have added the default field to the Image model to indicate the frontend that a particular image has to be shown among all the available images for a product. In fact, we can add different data to the image, making it richer than just an image file, and it could even have some behavior.

Many models that need more than one image

If there are two or more models that have nothing to do with each other, but all of them need to have attached several images, we could follow the same scheme we created before:

The problem with this is that we are basically repeating code, because we need to define different Image classes for every multi image model, storing the same data but the related model.

Inheritance

An easy way to avoid this, is by creating an abstract model which handles the image managing. All the concrete models that need this behavior just inherit from it:

With this approach we could also define some functions in the parent model, like getting the default image or thumbnails.

Composition

Although the previous solution is great in terms of code repetition and compliance with requirements, it’s not as good as it could be, because we would need to change the parent model of every model that will need several images, involving new migrations changing the models’ base, which is not as trivial as normal migrations. Django’s migrations scheme could make this fix really hard to make if our application is complex and already in production.

In addition to that, we should analyze the relation between the actual models and the MultiImage model, as this post suggests. We can notice that while an apple and a table are products, a product or a blog post are not a multi image model. They have multiple images instead.

To avoid all of the problems mentioned, we could implement composition using an ImageAlbum as an intermediate model between the models and the images.

We have used the One to One field to bind a model with an album, so note that if this model doesn’t have an album, an exception will be raised and will have to be managed.

Different upload paths

One thing that could happen is that we need to store our images in different paths, depending on the model name. For example:

We will need to define the upload path dynamically when the model instance is created. To do that, we can define a function which creates the correct path according to the model name, and we can pass that function to the upload_to setting of the ImageField:

Summing up

We have created a flexible design to upload multiple images for different models, giving more data to the images themselves, setting the upload path according to the model’s name and avoiding code repetition by implementing composition.

Thank you very much for reading this post and I hope it helps you for your projects. Follow me for upcoming posts, and I wish you good luck and happy coding!

Ibisdev

Developing your dreams, supporting your team

Thanks to Sandro Damilano

Juli Colombo

Written by

Developer. Makeup artist. Vegan. www.linkedin.com/in/julieta-colombo

Ibisdev

Ibisdev

Your development partner for specialized software solutions

Juli Colombo

Written by

Developer. Makeup artist. Vegan. www.linkedin.com/in/julieta-colombo

Ibisdev

Ibisdev

Your development partner for specialized software solutions

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store