0

I'm trying to set up magnific popup on django. My goal is to have one main picture in the homepage overview gallery view, which when clicked, would open a popup with the related images from the same photoshoot i.e. images with the same ID or PK.

I tried to apply the following approach but i just cannot get it to work, maybe someone could help me out in this

My models.py

class Item(models.Model):
name           = models.CharField(blank=False, max_length=200)    
category       = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
order          = models.IntegerField(blank=True, null=True)
active         = models.BooleanField(blank=True, default=False)
objects        = models.Manager()

class Meta:
    verbose_name_plural = 'items'

def __str__(self):
    return self.name

class ItemImage(models.Model):
image          = ProcessedImageField( 
                                blank=True, 
                                null=True,
                                processors=[ResizeToFit(width=1680, upscale=False)],
                                format='JPEG',
                                options={'quality':90})
order          = models.IntegerField(blank=True, null=True)
main           = models.BooleanField(blank=True, default=False)
cover          = models.BooleanField(blank=True, default=False)
item           = models.ForeignKey(Item, related_name='items', blank=True, null=True, on_delete=models.SET_NULL)
objects        = models.Manager()

class Meta:
    verbose_name_plural = 'item images'

Views.py

def portraits(request):
port = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
portall = ItemImage.objects.filter(item__category__slug='portraits', item__active=True).order_by('item__order')
context = {
    'main_portraits': port,
    'all_portraits': portall
        }
return render(request, 'gallery/portraits.html', context)

and Template:

{% block content %}

<div class="grid">
  {% for pic in main_portraits %}
    <div class="item">
      <div class="item">
          <div class="outer-text">
            <div class="text">
              {{ pic.item.name }}
              <p>Click to view gallery</p>
            </div>
          </div>
          <a><img class="lazy" alt=""
          sizes="(min-width:1400px) 1220px
                (min-width:1000px) 1000px,
                (min-width:500px) 700px,
                (min-width:320px) 420px,
                280px"
          srcset="{{ pic.image_xs.url }} 280w, 
                  {{ pic.image_s.url }} 420w,
                  {{ pic.image_m.url }} 700w,
                  {{ pic.image_l.url }} 1000w,
                  {{ pic.image_xl.url }} 1220w" />
          </a> {{ pic.item.pk }}
      </div>                
      <div class="lazy">
        {% for p in all_portraits %}
          <a href="{{ z.item.pk }}"></a>
        {% endfor %}
      </div>
    </div>
  {% endfor %}
</div>

{% endblock %}

I have set

z.item.pk 

just as a test, to see if any of my manipulations result in the pk's to bunch up. For example the first for-loop returns a picture with PK "24", I need for the second for-lop to return only images with the same PK; and so for every image. I think the answer might be connected with _set.all function, just like in the related question above, but I cant seem to get it to work in my case. Feels like I'm missing something here.

current output:

<div class="grid">

    <div class="item">
      <div class="item">
          <div class="outer-text">
            <div class="text">
              Palagā tītā
              <p>Click to view gallery</p>
            </div>
          </div>
          <a><img class="lazy" alt=""
          sizes="(min-width:1400px) 1220px
                (min-width:1000px) 1000px,
                (min-width:500px) 700px,
                (min-width:320px) 420px,
                280px"
          srcset="/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/958ba5dbee5efe28fd2f5054b8f819e1.jpg 280w, 
                  /media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/02d12ca7f0633fee2fc762cf96f7889e.jpg 420w,
                  /media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/ba5fa6633e92a288e3b2f47a713d64c2.jpg 700w,
                  /media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/fe0d559fef5b02434c43f841005d4961.jpg 1000w,
                  /media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/96d0e52dff14d1bc4b60bbec674565db.jpg 1220w" />
          </a> 24
      </div>                
      <div class="lazy">

          <a href="24"></a>

          <a href="24"></a>

          <a href="24"></a>

          <a href="26"></a>

          <a href="27"></a>

          <a href="27"></a>

          <a href="30"></a>

          <a href="31"></a>

      </div>
    </div>
reivan
  • 29
  • 1
  • 8
  • Per item how many main images are possible? – Arpit Svt Jan 28 '19 at 20:25
  • technically all of the images can be "main" as in they would appear in the gallery view, but the idea is to have one main image per photoshoot album. All of the images are added in the same manner through admin and one of them would be 'checked' marking it as thee main thumbnail image for the album. – reivan Jan 28 '19 at 20:53
  • I think its better idea to change the model design. – Arpit Svt Jan 28 '19 at 20:56
  • my model has proven to be quite functional, this is the last piece of the puzzle, I am sure there is a way to solve it – reivan Jan 28 '19 at 20:59

2 Answers2

0

You can break down the models like this it will make the querying easier.

# models.py
class Item(mdoels.Model):
    name = models.CharField(blank=False, max_length=200)
    category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
    ...
    display_image = models.ProcessedImageField(...)


class ItemImage(models.Model):
    item = models.ForeignKey(Item, related_name='images', blank=True, null=True, on_delete=models.SET_NULL)
    image = models.ProcessedImageField(...)
    ...


#views.py
def portraits(request):
    items = Item.objects.filter(category__slug='portraits', active=True)
    return render(request, 'gallery/portraits.html', context={items: items})

#template
{% for item in items %}

    <h1> {{item.name}} </h1>
    <img src={{item.display_image}} />

    {% for item_image in item.images.all %}
        <img src={{item_image.image}} />
    {% endfor %}

{% endfor %}
Arpit Svt
  • 1,153
  • 12
  • 20
0

You need prefiltered querysets containing the related images for every main image before handing over to the template.

def portraits(request):
    ports = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
    for p in ports:
        # You may not need the item__category__slug filter 
        # if there are only images of the same category 
        # associated with an item.
        # Also, if you want to exclude the main image 
        # from the set of related images, you need to add the filter
        # main=False

        p.related_images = ItemImage.objects.filter(item__category__slug='portraits', item__id=p.item.id)

    context = {
        'main_portraits': ports,
            }
    return render(request, 'gallery/portraits.html', context)

Then you can loop over main_portraits in the template, and get the related images for each main image in a nested loop:

{% for mainp in main_portraits %}
    {% for im in mainp.related_images %}
         {# do something with the related images #}
    {% endfor %}
{% endfor %}
Endre Both
  • 5,540
  • 1
  • 26
  • 31