3

I made image gallery with grid view, but I don't like the way that rows look like - vertical photos disrupt everything. As I don't want to manually change images order I'm looking for a way to sort them automaticaly by image height or just image orientation, so vertical photos go to the bottom in one row.

Thats how my model in Django looks like:

class Photo(models.Model):
    title = models.CharField(max_length=150)
    image = models.ImageField()
    description = models.TextField(blank=True)
    category = models.IntegerField(choices=CATEGORIES)
    published = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.title

Here is my grid_view:

def photos_grid(request):
    global cat_list
    photos = Photo.objects.order_by('published')
    output = {'photos': photos, 'categories': cat_list,}
    return render(request, 'photos/photos_grid.html', output)

I tried that (how to find height and width of image for FileField Django) way of getting image dimensions but I got

ValueError: invalid literal for int() with base 10: 'height'

every way I try to put it in my code. Other idea (by getting manually dimensions in views.py) works, but I can't put it together with my photos on the list so it get sorted.

Selcuk
  • 57,004
  • 12
  • 102
  • 110
Bruinen
  • 109
  • 7
  • Have you thought about using Sorl just to crop them all first and get rid of useless queries? – Andrey Shipilov May 05 '18 at 09:59
  • Yes, but some photos don't look properly when cropped - I had that problem on Facebook some time ago and hate when important part of the picure is not visible on thumbnail. – Bruinen May 05 '18 at 10:07
  • Then add the geometry to the model i.e. offset_x and offset_y. And crop respectively. Like so: http://dpaste.com/2KWFSHE – Andrey Shipilov May 05 '18 at 10:15

1 Answers1

1

You must include the height and width fields in your model, for example:

class Photo(models.Model):
    image = models.ImageField(height_field='image_height', width_field='image_width')
    image_height = models.IntegerField()
    image_width = models.IntegerField()
    ...

After migrating your database, you can write the following:

Photo.objects.all().order_by('image_height')

Edit: If you need to access the orientation, add another field, such as:

class Photo(models.Model):
    ...
    aspect_ratio = models.FloatField(blank=True, null=True)

then, override your save method to populate this field using height and width, i.e.:

class Photo(models.Model):
    ...
    def save(self, **kwargs):
        self.aspect_ratio = float(self.image_height) / float(self.image_width)
        super(Photo, self).save(kwargs)

You can then order by your new field, such as:

Photo.objects.all().order_by('aspect_ratio')
Selcuk
  • 57,004
  • 12
  • 102
  • 110