모든 페이지에 바닥글 생성

다음 단계는 포트폴리오 사이트의 모든 페이지에 바닥글을 만드는 것입니다. 바닥글에 소셜 미디어 링크 및 기타 정보를 표시할 수 있습니다.

기본 앱 추가

이제 base 라는 일반적인 목적의 앱을 생성합니다. base 앱을 생성하려면 다음 명령을 실행합니다:

python manage.py startapp base

base 앱을 생성한 후 사이트에 설치해야 합니다. mysite/settings/base.py 파일에서 INSTALLED_APPS 목록에 "base" 를 추가합니다.

탐색 설정 생성

이제 base/models.py 파일로 이동하여 다음 코드 줄을 추가합니다:

from django.db import models
from wagtail.admin.panels import (
    FieldPanel,
    MultiFieldPanel,
)
from wagtail.contrib.settings.models import (
    BaseGenericSetting,
    register_setting,
)

@register_setting
class NavigationSettings(BaseGenericSetting):
    linkedin_url = models.URLField(verbose_name="LinkedIn URL", blank=True)
    github_url = models.URLField(verbose_name="GitHub URL", blank=True)
    mastodon_url = models.URLField(verbose_name="Mastodon URL", blank=True)

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("linkedin_url"),
                FieldPanel("github_url"),
                FieldPanel("mastodon_url"),
            ],
            "소셜 설정",
        )
    ]

이전 코드에서 register_setting 데코레이터는 NavigationSettings 모델을 등록합니다. BaseGenericSetting 기본 모델 클래스를 사용하여 단일 페이지가 아닌 모든 웹 페이지에 적용되는 설정 모델을 정의했습니다.

이제 python manage.py makemigrationspython manage.py migrate 명령을 실행하여 데이터베이스를 마이그레이션합니다. 데이터베이스를 마이그레이션한 후 관리 인터페이스를 다시 로드합니다. _’wagtailsettings’는 등록된 네임스페이스가 아닙니다_라는 오류가 발생할 것입니다. 이는 wagtail.contrib.settings 모듈을 설치하지 않았기 때문입니다.

wagtail.contrib.settings 모듈은 모든 웹 페이지에 걸쳐 공통 설정을 보유하는 모델을 정의합니다. 따라서 BaseGenericSettingregister_setting 을 성공적으로 가져오려면 wagtail.contrib.settings 모듈을 사이트에 설치해야 합니다. wagtail.contrib.settings 를 설치하려면 mysite/settings/base.py 파일로 이동하여 INSTALLED_APPS 목록에 "wagtail.contrib.settings" 를 추가합니다:

INSTALLED_APPS = [
    # ...
    # wagtail.contrib.settings를 설치하려면 이 줄을 추가합니다:
    "wagtail.contrib.settings",
]

또한 settings 컨텍스트 프로세서를 등록해야 합니다. settings 컨텍스트 프로세서를 등록하면 사이트 전체 설정에 템플릿에서 액세스할 수 있습니다. settings 컨텍스트 프로세서를 등록하려면 mysite/settings/base.py 파일을 다음과 같이 수정합니다:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            os.path.join(PROJECT_DIR, "templates"),
        ],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",

                # _settings_ 컨텍스트 프로세서를 등록하려면 이것을 추가합니다:
                "wagtail.contrib.settings.context_processors.settings",
            ],
        },
    },
]

소셜 미디어 링크 표시

관리 인터페이스를 통해 추가한 소셜 미디어 링크를 표시하려면 템플릿을 제공해야 합니다.

mysite/templates 폴더에 includes 폴더를 생성합니다. 그런 다음 새로 생성된 mysite/templates/includes 폴더에 footer.html 파일을 생성하고 다음을 추가합니다:

<footer>
    <p>Wagtail로 구축됨</p>

    {% with linkedin_url=settings.base.NavigationSettings.linkedin_url github_url=settings.base.NavigationSettings.github_url mastodon_url=settings.base.NavigationSettings.mastodon_url %}
        {% if linkedin_url or github_url or mastodon_url %}
            <p>
                나를 팔로우하세요:
                {% if github_url %}
                    <a href="{{ github_url }}">GitHub</a>
                {% endif %}
                {% if linkedin_url %}
                    <a href="{{ linkedin_url }}">LinkedIn</a>
                {% endif %}
                {% if mastodon_url %}
                    <a href="{{ mastodon_url }}">Mastodon</a>
                {% endif %}
            </p>
        {% endif %}
    {% endwith %}
</footer>

이제 mysite/templates/base.html 파일로 이동하여 다음과 같이 수정합니다:

{% load static %}
{% load wagtailuserbar %}
<body class="{% block body_class %}{% endblock %}">
    {% wagtailuserbar %}

    {% block content %}{% endblock %}

    {# 파일에 이것을 추가합니다: #}
    {% include "includes/footer.html" %}

    {# 전역 자바스크립트 #}
    <script type="text/javascript" src="{% static 'js/mysite.js' %}"></script>

    {% block extra_js %}
    {# 추가 자바스크립트를 추가하려면 템플릿에서 이것을 재정의하십시오 #}
    {% endblock %}
</body>

이제 홈페이지를 다시 로드합니다. 홈페이지 하단에 소셜 미디어 링크가 표시됩니다.

Wagtail 스니펫으로 편집 가능한 바닥글 텍스트 생성

포트폴리오 바닥글에 소셜 미디어 링크만 있는 것은 이상적이지 않습니다. 사이트 크레딧 및 저작권 고지와 같은 다른 항목을 바닥글에 추가할 수 있습니다. 이를 수행하는 한 가지 방법은 Wagtail 스니펫 기능을 사용하여 관리 인터페이스에서 편집 가능한 바닥글 텍스트를 생성하고 사이트 바닥글에 표시하는 것입니다.

바닥글 텍스트 스니펫을 관리 인터페이스에 추가하려면 base/models.py 파일을 다음과 같이 수정합니다:

from django.db import models
from wagtail.admin.panels import (
    FieldPanel,
    MultiFieldPanel,

    # PublishingPanel 가져오기:
    PublishingPanel,
)

# RichTextField 가져오기:
from wagtail.fields import RichTextField

# DraftStateMixin, PreviewableMixin, RevisionMixin, TranslatableMixin 가져오기:
from wagtail.models import (
    DraftStateMixin,
    PreviewableMixin,
    RevisionMixin,
    TranslatableMixin,
)

from wagtail.contrib.settings.models import (
    BaseGenericSetting,
    register_setting,
)

# register_snippet 가져오기:
from wagtail.snippets.models import register_snippet

# ...NavigationSettings 모델 정의를 유지하고 FooterText 모델을 추가합니다:
@register_snippet
class FooterText(
    DraftStateMixin,
    RevisionMixin,
    PreviewableMixin,
    TranslatableMixin,
    models.Model,
):

    body = RichTextField()

    panels = [
        FieldPanel("body"),
        PublishingPanel(),
    ]

    def __str__(self):
        return "바닥글 텍스트"

    def get_preview_template(self, request, mode_name):
        return "base.html"

    def get_preview_context(self, request, mode_name):
        return {"footer_text": self.body}

    class Meta(TranslatableMixin.Meta):
        verbose_name_plural = "바닥글 텍스트"

이전 코드에서 FooterText 클래스는 여러 Mixins, 즉 DraftStateMixin, RevisionMixin, PreviewableMixin, TranslatableMixin 에서 상속됩니다. Django에서 Mixins 는 추가 기능을 정의하는 재사용 가능한 코드 조각입니다. Python 클래스로 구현되므로 해당 메서드와 속성을 상속할 수 있습니다.

FooterText 모델은 Wagtail 스니펫이므로 Mixins 를 모델에 수동으로 추가해야 합니다. 이는 스니펫이 자체적으로 Wagtail Pages 가 아니기 때문입니다. Wagtail Pages 는 이미 Mixins 를 가지고 있으므로 필요하지 않습니다.

DraftStateMixin 은 모든 비페이지 Django 모델에 추가할 수 있는 추상 모델입니다. 초안 또는 게시되지 않은 변경 사항에 사용할 수 있습니다. DraftStateMixinRevisionMixin 을 필요로 합니다.

RevisionMixin 은 모든 비페이지 Django 모델에 추가할 수 있는 추상 모델로, 인스턴스의 개정을 저장합니다. 페이지를 편집할 때마다 Wagtail은 새 Revision 을 생성하고 데이터베이스에 저장합니다. Revision 을 사용하여 변경 사항의 기록을 찾을 수 있습니다. Revision 은 또한 새 변경 사항이 라이브로 전환되기 전에 보관할 장소를 제공합니다.

PreviewableMixin 은 모든 비페이지 Django 모델에 추가할 수 있는 Mixin 클래스로, 변경 사항을 미리 볼 수 있습니다.

TranslatableMixin 은 모든 비페이지 Django 모델에 추가할 수 있는 추상 모델로, 번역 가능하게 만듭니다.

또한 Wagtail을 사용하면 스니펫에 대한 변경 사항에 대한 게시 일정을 설정할 수 있습니다. PublishingPanel 을 사용하여 FooterText 에서 개정을 예약할 수 있습니다.

__str__ 메서드는 FooterText 클래스 인스턴스의 사람이 읽을 수 있는 문자열 표현을 정의합니다. “바닥글 텍스트” 문자열을 반환합니다.

get_preview_template 메서드는 미리보기를 렌더링하기 위한 템플릿을 결정합니다. “base.html” 템플릿 이름을 반환합니다.

get_preview_context 메서드는 미리보기 템플릿을 렌더링하는 데 사용할 수 있는 컨텍스트 데이터를 정의합니다. 본문 필드의 내용을 값으로 하는 “footer_text” 키를 반환합니다.

Meta 클래스는 모델에 대한 메타데이터를 보유합니다. TranslatableMixin.Meta 클래스에서 상속되며 verbose_name_plural 속성을 _”바닥글 텍스트”_로 설정합니다.

이제 python manage.py makemigrationspython manage.py migrate 를 실행하여 데이터베이스를 마이그레이션합니다. 마이그레이션 후 서버를 다시 시작하고 관리 인터페이스를 다시 로드합니다. 이제 사이드바에서 스니펫을 찾을 수 있습니다.

바닥글 텍스트 표시

이 튜토리얼에서는 사용자 지정 템플릿 태그를 사용하여 바닥글 텍스트를 표시합니다.

base 폴더에 templatetags 폴더를 생성합니다. 새로 생성된 templatetags 폴더 안에 다음 파일을 생성합니다:

  • __init__.py

  • navigation_tags.py

base/templatetags/__init__.py 파일은 비워두고 base/templatetags/navigation_tags.py 파일에 다음을 추가합니다:

from django import template

from base.models import FooterText

register = template.Library()


@register.inclusion_tag("base/includes/footer_text.html", takes_context=True)
def get_footer_text(context):
    footer_text = context.get("footer_text", "")

    if not footer_text:
        instance = FooterText.objects.filter(live=True).first()
        footer_text = instance.body if instance else ""

    return {
        "footer_text": footer_text,
    }

이전 코드에서 template 모듈을 가져왔습니다. 이를 사용하여 템플릿 태그와 필터를 생성하고 렌더링할 수 있습니다. 또한 base/models.py 파일에서 FooterText 모델을 가져왔습니다.

register = template.Library() 는 템플릿 모듈에서 Library 클래스의 인스턴스를 생성합니다. 이 인스턴스를 사용하여 사용자 지정 템플릿 태그와 필터를 등록할 수 있습니다.

@register.inclusion_tag("base/includes/footer_text.html", takes_context=True)get_footer_text 라는 포함 태그를 등록하는 데코레이터입니다. "base/includes/footer_text.html" 은 포함 태그를 렌더링하는 데 사용할 템플릿 경로입니다. takes_context=Truefooter_text.html 템플릿의 컨텍스트가 포함 태그 함수에 인수로 전달됨을 나타냅니다.

get_footer_text 포함 태그 함수는 context 라는 단일 인수를 받습니다. context 는 태그를 사용할 템플릿 컨텍스트를 나타냅니다.

footer_text = context.get("footer_text", "")footer_text 키를 사용하여 컨텍스트에서 값을 검색하려고 시도합니다. footer_text 변수는 검색된 값을 저장합니다. 컨텍스트에 footer_text 값이 없으면 변수는 빈 문자열 "" 을 저장합니다.

get_footer_text 포함 태그 함수의 if 문은 footer_text 가 컨텍스트에 존재하는지 확인합니다. 존재하지 않으면 if 문은 데이터베이스에서 FooterText 의 첫 번째 게시된 인스턴스를 검색합니다. 게시된 인스턴스가 발견되면 문은 본문 내용을 추출합니다. 그러나 게시된 인스턴스가 없으면 기본적으로 빈 문자열이 됩니다.

마지막으로, 함수는 검색된 footer_text 내용의 값을 가진 "footer_text" 키를 포함하는 사전을 반환합니다. 이 사전을 footer_text 템플릿을 렌더링할 때 컨텍스트 데이터로 사용할 것입니다.

반환된 사전을 사용하려면 base 폴더에 templates/base/includes 폴더를 생성합니다. 그런 다음 base/templates/base/includes/ 폴더에 footer_text.html 파일을 생성하고 다음을 추가합니다:

{% load wagtailcore_tags %}

<div>
    {{ footer_text|richtext }}
</div>

mysite/templates/includes/footer.html 파일을 수정하여 footer_text 템플릿을 바닥글에 추가합니다:

{# 파일 상단에 navigation_tags 로드: #}
{% load navigation_tags %}

<footer>
    <p>Wagtail로 구축됨</p>

    {% with linkedin_url=settings.base.NavigationSettings.linkedin_url github_url=settings.base.NavigationSettings.github_url mastodon_url=settings.base.NavigationSettings.mastodon_url %}
        {% if linkedin_url or github_url or mastodon_url %}
            <p>
                나를 팔로우하세요:
                {% if github_url %}
                    <a href="{{ github_url }}">GitHub</a>
                {% endif %}
                {% if linkedin_url %}
                    <a href="{{ linkedin_url }}">LinkedIn</a>
                {% endif %}
                {% if mastodon_url %}
                    <a href="{{ mastodon_url }}">Mastodon</a>
                {% endif %}
            </p>
        {% endif %}
    {% endwith %}

    {# footer_text 추가: #}
    {% get_footer_text %}
</footer>

이제 서버를 다시 시작하고 홈페이지를 다시 로드합니다. Wagtail 스니펫을 렌더링하는 방법에 대한 자세한 내용은 스니펫 렌더링을 참조하십시오.

잘하셨습니다! 👏 이제 포트폴리오 사이트의 모든 페이지에 바닥글이 있습니다. 이 튜토리얼의 다음 섹션에서는 홈페이지 및 추가할 다른 페이지에 연결하기 위한 사이트 메뉴를 설정하는 방법을 배웁니다.