Forums

Loading images with Django

I am trying to display a different background image using CSS every time a different instance of a model is shown on a web page. I can successfully load the different images using:

background-image:url('{{ STATIC_URL }}project/images/{{ object.id }}/bg.jpg')

However, I want to improve this so if a given directory does not exist, a fall back image will be displayed. Is there anyway to do this using the template system in django?

Jinja2 tends to make it deliberately tricky to run arbitrary Python in templates because it's generally regarded as poor practice to embed too much logic in them. You could write a Python function and expose that to the template, but in this case I suspect your best option is to have the Python back-end code generate the path to the image based on whether the file exists and just expose that to the template:

background-image: url('{{ STATIC_URL }}project/images/{{ image_url }}');

What Cartroo said, plus I would probably put it as a method on the object.

class MyObject(models.Model):

    image_url = models.CharField()

    def image_url(self):
        if os.path.exists(self.image_url)
            return self.image_url
        return 'default_image'

Then in the template:

background-image: url('{{ STATIC_URL }}project/images/{{ my_object.image_url }}');

Thanks, implemented a has_image and image_url method for the object so I can differentiate the types of image and it works great.

Lovely, I'm all about making models do all the work at the moment.

Ah, that's not a statement you want taken out of context...

But yes, I think too much logic often gets embedded into the view. I always ask myself "would the result of this condition change between..."

  • Different visual layouts.
  • Rendering on different devices.
  • Rendering in different languages or locales (including e.g. right-to-left languages).
  • Rendering for users with different accessibility needs.

If the answer to any of the questions is "yes", I think it's at least potentially sensible to put the logic in the view. If all the answers are "no" then I think it's pretty unequivocal that it should go into the model.

Of course, issues like full i18n are tricky and often still require model input anyway (even if it's just to select one of a set of views based on the locale). But I find thinking in those terms tends to focus me away from what's easy to implement towards what's the cleanest interface.