Change image src url using HttpResponse in Django views

Is there any way of redirecting an image’s ‘request’ URL in Django views, to an Nginx server so that Django doesn’t have to serve the image itself? The background to my questions has to do with image tracking, which for obvious reasons requires a trip to Django.

For example, I have a webpage with an image, say;

<img src="https://mydjangoserver.com/uuid/image-url/image.jpg">

Which is passed to views, the UUID is stripped, and src url for the image is changed to the URL of the image held on an NGINX server, say,

https://my-nginx-server.com/image.jpg

The image is then loaded within the original html page that first requested the image.

Any advice on how to redirect the image src url to avoid it being served by Django would be very much appreciated.

Are you using the whitenoise library to serve static or media assets? What does the template look like that would result in the following HTML?

<img src="https://mydjangoserver.com/uuid/image-url/image.jpg">

Generally, unless you’re using whitenoise (or the development server) django doesn’t serve your static or media assets.

Thank you Tim.

Actually, the image is contained in an email, the link for which is in exactly the same format as my post.

The site is is not in development mode and I am not using whitenoise.

I use the following code to serve the image (after processing the UUID):

def track_image(request, key1, key2):

    file_path = f'{settings.MEDIA_ROOT}/media/newsletter/{key1}/{key2}'

    with open(file_path, 'rb') as fh:
        response = HttpResponse(fh.read(), content_type="image/jpeg")
        response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
        return response

It works fine, but I wanted a better way of achieving the same by simply changing the url and get NGINX to serve the file instead.

If you’re storing this in a models.ImageField or models.FileField, I’d recommend using model_instance.image_field.url rather than attempting to generate the file_path, then having nginx serve all requests that are made to the MEDIA_URL as defined your settings.

Thanks again Tim, I very much appreciate your help.

Just running through the steps quickly:
The email template is compiled by Django during which the image URL is set:

<img src="https://mydjangoserver.com/uuid/image-url/image.jpg">

The email is then sent to the recipient.

When the recipient views the email, a request for the image is sent to Django views (assuming that viewing email images is allowed by the email client), whereupon the UUID is stripped and the image is served.

Maybe it’s my inexperience with Django, but I do not understand how using a model_instance.image_field.url would help. Could you perhaps give me an example in the context of my def track_image(request, key1, key2): code above?
Thanks again.

@pcd1000 Ah I’m sorry it took me a while to get on the same page.

I think what you want is the following:

from django.shortcuts import redirect

def track_image(request, key1, key2):
    model_instance = YourModel.objects.get(key1=key1, key2=key2)
    return redirect(model_instance.image_field.url)

Your track_image view should take the parameters that you can look up the model instance. Then it should return a redirect response to the instance’s image file’s url.

This will require the client to do another round trip, but unless your media files are on the same machine the additional overhead compared to reading the images data in and then rendering it as a response should be insignificant.

Thank you so much Tim!

You got me thinking and changing your code slightly from:

return redirect(model_instance.image_field.url)
to
return redirect('https://my-nginx-webserver/image.jpg')

Worked.
Thanks again!

I’m glad you were able to find something that works for you!