What's the best way to deliver images?

Here’s a simple example of how I’m delivering images. Is there a better way?

# django_app/forms.py
from django.forms import ModelForm     
from .models import Photo

class PhotoForm(ModelForm):

    class Meta:
        model = Photo
        fields = ['image']
# django_app/models.py
from django.db import models

class Photo(models.Model):
    image = models.ImageField(upload_to='photos/')
# django_app/views.py
from django.shortcuts import render, redirect
   
from .models import Photo
from .forms import PhotoForm

def upload(request):
  context = dict( backend_form = PhotoForm())

  if request.method == 'POST':
    form = PhotoForm(request.POST, request.FILES)
    if form.is_valid():
        form.save()
        return redirect('display')
  return render(request, 'upload.html', context)

def display(request):
    photos = Photo.objects.all()  # Retrieve all photos from the database
    return render(request, 'display.html', {'photos': photos})
<!-- django_app/templates/display.html -->
<body>
    <h1 class="image-heading">Displayed Images</h1>
    <div class="image-grid">
        {% for photo in photos %}
             <img src="{{ photo.image.url }}" alt="Image"> 
            
        {% endfor %}
    </div>
    <div>
</body>

Welcome!

Define “better” here. What is it that you think could be improved? Or, to phrase this a little differently, what would be improved by adopting a different approach?

(I generally work under the principle that if it works and doesn’t eat the machine in the process - or cause problems later on, then it’s “good enough” - and my time is better spent on adding new features.)

Would this be “good enough” when handling a large volume of images?
How would people generally deal with cropping the images and sizing them properly to fit the webpage design, especially when dealing with a lot of them?

For displaying them, sure - it’s as good as anything else. The images are not part of the page. What’s you’re sending is a URL to the image so that the browser can issue a separate request for it. That is where the bottleneck is going to be - in the deliver of “n” images, not in the production of the html that defines the requests to be made.

That’s usually done outside your framework. That’s not something Django is going to do for you.

Do you mean that cropping and sizing the images for display would be done by a graphic designer, or using Cloudinary’s AI functionality? Python libraries?

However you want to do it. Use whatever tooling you’re comfortable with.
I’m only pointing out that Django isn’t going to do that for you.

OK, thanks.
Just to let you know, this code did it for me. It let me use AI in my Django forms and models to fit any image within any bounding box, so I can handle a large number of images knowing it’s going to look when delivered. This is using Cloudinary:

django_app/forms.py

from django.forms import ModelForm
from cloudinary.forms import CloudinaryFileField
from .models import Photo

class PhotoForm(ModelForm):
image = CloudinaryFileField()

class Meta:
    model = Photo
    fields = '__all__'

def __init__(self, *args, **kwargs):
   super().__init__(*args, **kwargs)
   self.fields['image'].options={
       'tags': 'new_image',
       'format': 'png'

}

from django.db import models
from cloudinary.models import CloudinaryField

class Photo(models.Model):
image = CloudinaryField(‘image’)

django_app/views.py

from django.shortcuts import render, redirect

from .models import Photo
from .forms import PhotoForm

def upload(request):
context = dict( backend_form = PhotoForm())

if request.method == ‘POST’:
form = PhotoForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect(‘display’)
return render(request, ‘upload.html’, context)

def display(request):
photos = Photo.objects.all() # Retrieve all photos from the database
return render(request, ‘display.html’, {‘photos’: photos})

Displayed Images

{{% for photo in photos %} {% load cloudinary %} {% cloudinary photo.image quality='auto' width=200 height=200 crop='pad' background='gen_fill:ignore-foreground_true' %} {% endfor %}}
1 Like