Wagtail Photography 8

OK let’s add some social media links. Obviously we can add them to the template directly but that doesn’t seem very user friendly. In order to accomplish this, we will use Site Settings. That way, the client can edit them in the admin interface. Do we need a new app for them? I say yes, because I have used this app in multiple Wagtail projects. If that doesn’t make it reusable, I don’t know what does.


python manage.py startapp socialmedia

Don’t forget to add it under INSTALLED_APPS in portfolio/settings/base.py.


INSTALLED_APPS = [
    ...,
    'socialmedia',
    ...
]

Also, since we are gonna access the settings (that we are about to implement) in the templates, we also need to add the settings context processor to our settings file. At some point I want to write a nice post about context processors in Django, let’s hope I do.

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...,
                'wagtail.contrib.settings.context_processors.settings',
            ]
        }
    }
]

Oh and you also have to add another thing to your installed_apps:

INSTALLED_APPS = [
    'wagtail.contrib.settings',
]

Now, in socialmedia/models.py:

from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel
from wagtail.contrib.settings.models import BaseSetting, register_setting
from wagtail.images.edit_handlers import ImageChooserPanel


@register_setting
class SocialMediaSettings(BaseSetting):
    """Social media settings for the website."""

    email = models.EmailField(blank=True, null=True,
                              help_text="Insert your email")
    instagram = models.CharField(
        blank=True, null=True, help_text="Instagram username", max_length=100)
    facebook = models.CharField(
        blank=True, null=True, help_text="Facebook username", max_length=100)

    panels = [
        MultiFieldPanel([
            FieldPanel("email"),
            FieldPanel("instagram"),
            FieldPanel("facebook"),
        ], heading="Social Media Settings",)
    ]


@register_setting
class LogoImage(BaseSetting):
    """Image chooser for the footer."""

    image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.SET_NULL,
        null=True,
        blank=False,
        related_name="+"
    )

    panels = [
        ImageChooserPanel("image"),
    ]

We are inheriting from BaseSetting for both of them and register using the register_setting decorator. That way SocialMediaSettings and LogoImage links will appear in the Settings menu in the admin interface of Wagtail. For the Social Media Settings, I defined three fields (that the client required, you can add more or fewer if neccessary). Then I added them to a MultiFieldPanel in a panels setting to the model. (Again remember that it is panel and not content_panels since we are not dealing with a Page. I will keep writing this as it took me longer than I’m proud of to understand why sometimes the code had panels and why sometimes it had content_panels). For the LogoImage setting, it only has an image associated which is a ForeignKey model to the in-built wagtailimages.Image. We are able to choose it using an ImageChoosePanel. Pretty simple to implement these.

Don’t forget to make your migrations and migrate.


python manage.py makemigrations
python manage.py migrate

Now, in the base.html template I will simply put a small image in the center and some links on either side. Feel free to customise it as you wish.

In base.html, first import the wagtailimages tags at the top:

...
{% load wagtailimages_tags %}

Then, in our footer:


  <nav class="navbar fixed-bottom navbar-dark bg-dark">
    <div class="container-fluid justify-content-center">
      <a class="pr-2" href="mailto: {{ settings.socialmedia.SocialMediaSettings.email}}">ICON</a>
      <a class="pr-2" href="https://www.instagram.com/{{settings.socialmedia.SocialMediaSettings.instagram}}" target="_blank" rel="noopener noreferrer">ICON</a>
      <a class="" href="https://www.facebook.com/{{settings.socialmedia.SocialMediaSettings.facebook}}" target="_blank" rel="noopener noreferrer">ICON</a>
      {% image settings.socialmedia.LogoImage.image height-120 as logo_image%}
      <a class="navbar-brand" href="/">
        <img src="{{logo_image.url}}" class="rounded mx-auto d-block w-50" style="opacity:1;">
      </a>
      <p class="navbar-brand">
        &#169; 2021 AUTHOR NAME
      </p>
    </div>
  </nav>

Again, this is to illustrate its usage. Not trying to win any design awards for this post. Notice that to add a setting, we do {{settings.APPNAME.MODEL.FIELD}}, like settings.socialmedia.SocialMediaSettings.email, settings.socialmedia.SocialMediaSettings.instagram or settings.socialmedia.LogoImage.image. Being able to access them through settingsDOTsomething comes from us adding the setting context processors to our settings. And that’s it. If you edit the various settings in the admin interface, we now have intergrations for social media stuff.

Until next time! Next post will be on CNLearn, so might be a while until the next Wagtail post. I decided to rewrite quite a few things in the way I implemented CNLearn, so I will rewrite the old posts from the CNLearn website and add them here and put a landing page while I am putting some finishing touches on version 0.1 of the web version as well.