churcht
churcht

Reputation: 41

Re-using wagtail page field in a snippet like way

Here's what I'm looking to do: create a horizonal scroll of images/logos which scroll across the foot of the screen on most of a sites pages - a marquee, tickertape something like that.. I'm okay with the CSS/html I have that working, the issue is I don't want to hardcode the images/logos into the html.

Since this isn't really a page I was thinking the best why to do this would be to use a snippet and set-up the contents of the marquee using a standard django model. Only thing is, the site is for a pro athlete and the logos are the sponsor logos - so there is already a wagtail page for each sponsor and where there is a sponsor page there is also the sponsor's logo. The logos are already saved in the database so it's would seem unnecessary to re-implement code to load and retrieve each logo a second time.

Is there a way to use to use an item in an existing page (in this case the image/logo) with a snippet? As a newbie I can well imagine there's a much better way to do this without using a snippet but I cannot see how, can anyone help?

Here's the code for the sponsors (or partners) index and page

class PartnerIndexPage(Page):
    intro = StreamField(BaseStreamBlock(),
                        verbose_name="Introduction",
                        blank=True,
                        use_json_field=True, )

    def get_context(self, request, *args, **kwargs):
        # restrict context to live, public and effective_end_date > today

        context = super().get_context(request)
        today = date.today()
        partnerpages = PartnerPage.objects.child_of(self).live().public().filter(effective_end_date__gte=today)
        context['partnerpages'] = partnerpages
        return context

    subpage_types = ['PartnerPage']
    parent_page_types = ['home.HomePage']

    content_panels = Page.content_panels + [
        FieldPanel('intro', classname="full")
    ]


class PartnerPage(Page):
    class LogoOrientation(models.IntegerChoices):
        L = 1, _('Landscape')
        P = 2, _('Portrait')
        S = 3, _('Square or Circular')

    name = models.CharField(blank=False, max_length=64,
                            help_text="E.g. IBM, Toyota, Ferrari, etc.")
    effective_end_date = models.DateField("End of partnership date", null=True,
                                          help_text="Set the date when partner's details will no longer be "
                                                    "visible on the site")
    tag_line = models.CharField(blank=True, null=True, max_length=64,
                                help_text="This isn't tags like in the news but more like 'Vorsprung durch Technik'")
    body = StreamField(BaseStreamBlock(),
                       verbose_name="Page body",
                       help_text="Partner information",
                       blank=True,
                       use_json_field=True, )

    phone = models.CharField(blank=True, max_length=32)
    email = models.CharField(blank=True, max_length=64)
    web = models.URLField(blank=True, help_text=_("Homepage URL"))
    facebook = models.URLField(blank=True, help_text=_("Facebook URL"))
    twitter = models.URLField(blank=True, help_text=_("Twitter URL"))
    youtube = models.URLField(blank=True, help_text=_("YouTube URL"))
    instagram = models.URLField(blank=True, help_text=_("Instagram URL"))
    google = models.URLField(blank=True, help_text=_("Google URL"))
    pinterest = models.URLField(blank=True, help_text=_("Pinterest URL"))

    logo_orientation = models.IntegerField(choices=LogoOrientation.choices, default=LogoOrientation.L)

    def main_image(self):
        gallery_item = self.partner_logo.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

    # search_fields = Page.search_fields + [
    # index.SearchField('name'),
    # index.SearchField('role'),
    # ]

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            FieldPanel('effective_end_date'),
        ], heading="Meta Information"),
        MultiFieldPanel([
            FieldPanel('name'),
            FieldPanel('tag_line'),
            FieldPanel('body'),
        ], heading="Partner Display Information"),
        MultiFieldPanel([
            FieldPanel('phone'),
            FieldPanel('email'),
            FieldPanel("web"),
            FieldPanel("facebook"),
            FieldPanel("twitter"),
            FieldPanel("youtube"),
            FieldPanel("instagram"),
            FieldPanel("google"),
            FieldPanel("pinterest"),
        ], heading="Contact information, website and social media"),
        MultiFieldPanel([
            #FieldPanel("logo_orientation"),
            InlinePanel('partner_logo', label="Partner logo"),
        ], heading="Logo Information"),
    ]

    parent_page_types = ['PartnerIndexPage']
    subpage_types = []

    class Meta:
        verbose_name = "partner page"


class PartnerPageGalleryImage(Orderable):
    page = ParentalKey(PartnerPage, on_delete=models.CASCADE, related_name='partner_logo')
    image = models.ForeignKey(
        'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
    )
    caption = models.CharField(blank=True, max_length=256)

    panels = [
        FieldPanel('image'),
        FieldPanel('caption'),
    ]

Upvotes: 0

Views: 197

Answers (2)

churcht
churcht

Reputation: 41

It may be useful to someone to know how this problem was resolved. As usual there are probably many other methods, but this one worked for me.

I didn't fancy a re-writing the code, so I went with a custom template tag, which seemed like the simplest way to get the images I needed into the marquee. By using a template tag I could write some python code to filter out unwanted images, e.g. companies no longer sponsoring the athlete. The method followed is described in the docs: https://docs.wagtail.org/en/stable/topics/snippets/rendering.html#including-snippets-in-template-tags

Hope this helps.

Upvotes: 0

Rich - enzedonline
Rich - enzedonline

Reputation: 1258

I probably would have set up the partners as a snippet, either link the partner page to the partner model via foreign key relationship field and add the additional page data, or include everything (including the streamfield) in the snippet and use routable pages to serve the partner page & index.

With your setup, you could create the marquee as snippet and use foreignkey to the partner page and pull the info from that. I think it's possible to limit the PageChooser to certain page types. Migrating your partner info into a snippet model would be the easier route though.

Upvotes: 0

Related Questions