0

I'm trying to create an index page containing links to multiple photo galleries in Wagtail. The GalleryIndexPage model looks like this:

class GalleryIndexPage(Page):
  subpage_types = ['home.GalleryPage']

  gallery_thumb = StreamField ([
      ('cover_photo', ImageChooserBlock()),
      ('title', blocks.CharBlock()),
      ('link', URLBlock()),
  ])

  content_panels = Page.content_panels + [
      StreamFieldPanel('gallery_thumb'),
  ]

I'm having difficulty rendering it into the template with a "gallery-item" class around each set of data. I realize that it is currently looping through and adding a class of "gallery-item" to each block inside the Streamfield, rather than around the whole Streamfield set. Here is my template code:

<div class="photo-gallery">
{% for block in self.gallery_thumb %}
<div class="gallery-item">
  {% if block.block_type == 'cover_photo' %}
  <div class="thumb">
    {% image block.value fill-200x150 %}
  </div>
  {% endif %}
  {% if block.block_type == 'title' %}
  <div class="title">
    <p>{{ block.value }}</p>
  </div>
  {% endif %}
  {% if block.block_type == 'link' %}
  <div class="link">
    <a href="{{ block.value }}">View Gallery</a>
  </div>
  {% endif %}
</div>
{% endfor %}

Is there another way I should approach this?

EDIT: I have added a StructBlock within my StreamField like so:

class GalleryIndexPage(Page):
  subpage_types = ['home.GalleryPage']

  gallery = StreamField ([
      ('gallery_item', blocks.StructBlock([
          ('cover_photo', ImageChooserBlock()),
          ('title', blocks.CharBlock()),
          ('link', URLBlock()),
      ], icon='user'))
  ])

  content_panels = Page.content_panels + [
      StreamFieldPanel('gallery'),
  ]

I'm not sure how to access these values in my template? Here is what I have so far:

  <div class="photo-gallery">
    {% for block in self.gallery %}
    <div class="gallery-item">
      <div class="thumb">
        {% image self.cover_photo width-200 %}
      </div>
      <div class="title">
        <p>{{ self.title }}</p>
      </div>
      <div class="link">
        <a href="{{ self.link }}">>> View Gallery</a>
      </div>
    </div>
    {% endfor %}
  </div> 
kbdev
  • 1,225
  • 1
  • 13
  • 33

2 Answers2

3

It seems like what you want is a single gallery_item block that consists of an image, title, and link. You can do this by creating your own block type out of simpler block types. See http://docs.wagtail.io/en/v1.5.3/topics/streamfield.html#structural-block-types

You could do something like this:

('gallery_item', blocks.StructBlock([
    ('title', blocks.CharBlock()),
    ('link', blocks.URLBlock()),
    ('image', ImageChooserBlock()),
], icon='xyz'))

You can also create this as a Python class, which is what I usually prefer to do, this is covered in the last part of the section I linked to above.

You can create your own template for this block.

Within the template, each block has two properties, value and block_type. So you would access, for example, the title with {{ self.title.value }}.

See http://docs.wagtail.io/en/v1.5.3/topics/streamfield.html#template-rendering

Brett
  • 4,341
  • 2
  • 19
  • 17
  • I have used your suggestion above, which seems to work great in the admin, but I'm having trouble accessing these values in the template. Question updated above to show what I've attempted. Thanks! – kbdev Aug 08 '16 at 14:19
  • Added some more info, I didn't test but I'm pretty sure that you're just missing the `.value` property, let me know if it's not working for you. – Brett Aug 08 '16 at 22:09
  • Yes, I was just missing the `.value` property. Thanks again for your help. – kbdev Aug 09 '16 at 15:24
  • Is there a way to limit to just the 12 latest images? – kbdev Nov 07 '19 at 20:17
  • 1
    @kbdev In a template you can probably use the builtin filter `slice` to get the first or last _n_ items of a list. https://docs.djangoproject.com/en/dev/ref/templates/builtins/#slice – Brett Nov 08 '19 at 00:33
2

I was able to access the values of the StructBlock in my template using this code:

<div class="photo-gallery">
{% for block in self.gallery %}
<div class="gallery-item">
  <div class="thumb">
    {% image block.value.cover_photo fill-200x150 %}
  </div>
  <div class="title">
    <p>{{ block.value.title }}</p>
  </div>
  <div class="link">
    <a href="{{ block.value.link }}">>>View Gallery</a>
  </div>
</div>
{% endfor %}

Thanks so much for your assistance!

kbdev
  • 1,225
  • 1
  • 13
  • 33