Wagtail에서 Menu를 관리하는 방법에 대해서 알아보려고 한다. 

Navigation Bar나 Footer에 표시된 Menu를 누르면 관련 링크로 이동하는 것인데,

하드 코딩없이 서버에서 Data로 관리하는 방법이다. 

 

새로운 menus App을 만들어서 진행했다. 

 

1. Models.py

"""Menus models"""
from django.db import models

from django_extensions.db.fields import AutoSlugField

from wagtail.admin.edit_handlers import (
    MultiFieldPanel,
    InlinePanel,
    FieldPanel,
    PageChooserPanel,
)
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail.snippets.models import register_snippet
from wagtail.core.models import Orderable


class MenuItem(Orderable):

    link_title = models.CharField(
        blank=True,
        null=True,
        max_length=50,
    )
    link_url = models.CharField(
        max_length=500,
        blank=True,
    )
    link_page = models.ForeignKey(
        "wagtailcore.Page",
        null=True,
        blank=True,
        related_name="+",
        on_delete=models.CASCADE,
    )
    open_in_new_tab = models.BooleanField(default=False, blank=True)

    page = ParentalKey("Menu", related_name="menu_items")

    panels = [
        FieldPanel("link_title"),
        FieldPanel("link_url"),
        PageChooserPanel("link_page"),
        FieldPanel("open_in_new_tab"),
    ]

    @property
    def link(self) -> str:
        if self.link_page:
            return self.link_page.url
        elif self.link_url:
            return self.link_url
        return '#'

    @property
    def title(self):
        if self.link_page and not self.link_title:
            return self.link_page.title
        elif self.link_title:
            return self.link_title
        return "Missing Title"


@register_snippet
class Menu(ClusterableModel):
    """The main menu clusterable model."""

    title = models.CharField(max_length=100) 
    slug = AutoSlugField(populate_from="title", editable=True)

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("title"),
                FieldPanel("slug"),        
            ], heading="Menu",
        ),
        InlinePanel("menu_items", label="Menu Item")
    ]

    def __str__(self):
        return self.title

Model은 Orderable과 ClusterableModel 2개를 만들어주었다. 간단하게 설명하자면 Orderable은 순서배치가 가능한 모델을 말하고 Clusterable은 나열가능한 모델을 갖는 모델을 말한다. 즉, Clusterable을 순서배치가 가능한 Orderable 모델을 가질 수 있다. 

 

@property를 통해 link title과 link url을 리턴해주었다. 

def에 -> str을 사용하면 리턴값이 문자열이 된다. 

 

django_extensions에 AutoSlugField가 있다. 

    title = models.CharField(max_length=100) 
    slug = AutoSlugField(populate_from="title", editable=True)

populate_form에 slug로 변환할 변수를 넣으면 자동으로 slug를 만들어준다. 수정가능하게 하고 싶다면 eidtable값을 True로 해준다.

 

 

2. menus_tags.py

menus/templatetags/menus_tags.py

from django import template

from ..models import Menu

register = template.Library()

@register.simple_tag()
def get_menu(slug):
    return Menu.objects.get(slug=slug)

 

 

Custom Template tag 기능을 사용하여 get_menu라는 이름의 함수를 만들어준다.

template에서 get_menu를 호출하면 Menu objects에서 slug 값이 같은 객체를 찾아서 리턴해준다. 

 

 

3. Template

admin 페이지에서 snippets에 있는 Menu로 이동해서 Main Nav라는 title의 모델을 하나 만들어준다.

 

 

base.html

{% load menus_tags %}

{% get_menu "main-nav" as navigation %}

{% for item in navigation.menu_items.all %}
  <li class="nav-item">
  	<a class="nav-link" href="{{ item.link }}"{% if item.open_in_new_tab %} target="_blank"{% endif %}>{{ item.title }}</a>
  </li>
{% endfor %}

 

main-nav의 변수를 slug로 get_menu 함수에 전달해서 return 값을 받아 navigation이라는 template 변수로 받는다. 

 

이후 for문법을 사용하여 네비게이션을 설정해주면 된다. 

(참고로 a태그에 target을 _blank을 주면 새로운 창을 열어서 표시한다.)

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail API v2 Exposing Custom Fields  (0) 2021.11.24
Wagtail API v2 Settings(Headless CMS)  (0) 2021.11.24
Wagtail, Django Paginator  (0) 2021.11.21
Wagtail StructValue  (0) 2021.11.18
Wagtail Sitemap  (0) 2021.11.17

+ Recent posts