스니펫 렌더링

Django 모델로서 스니펫은 사용자 지정 템플릿 태그를 사용하여 Django 템플릿에서 렌더링할 수 있습니다. 또는 Wagtail 페이지 렌더링 프로세스의 일부로 포함될 수도 있습니다.

템플릿 태그에 스니펫 포함

템플릿에 스니펫을 사용할 수 있도록 하는 가장 간단한 방법은 템플릿 태그를 사용하는 것입니다. 이는 대부분 일반 Django로 수행되므로 사용자 지정 템플릿 태그에 대한 Django 문서를 검토하는 것이 더 도움이 될 수 있습니다. 기본 사항을 살펴보고 Wagtail에 대한 고려 사항을 지적하겠습니다.

먼저 앱 내의 templatetags 폴더에 새 Python 파일을 추가합니다. 예를 들어 myproject/demo/templatetags/demo_tags.py 입니다. 일부 Django 모듈과 앱의 모델을 로드하고 register 데코레이터를 준비해야 합니다.

from django import template
from demo.models import Advert

register = template.Library()

# ...

# Advert 스니펫
@register.inclusion_tag('demo/tags/adverts.html', takes_context=True)
def adverts(context):
    return {
        'adverts': Advert.objects.all(),
        'request': context['request'],
    }

@register.inclusion_tag() 는 두 개의 변수를 사용합니다. 템플릿과 해당 템플릿에 요청 컨텍스트를 전달해야 하는지 여부를 나타내는 부울입니다. pageurl 과 같은 일부 Wagtail 특정 템플릿 태그는 작동하려면 컨텍스트가 필요하므로 사용자 지정 템플릿 태그에 요청 컨텍스트를 포함하는 것이 좋습니다. 템플릿 태그 함수는 인수를 사용하고 광고를 필터링하여 모델의 특정 인스턴스를 반환할 수 있지만, 간결성을 위해 Advert.objects.all() 만 사용하겠습니다.

다음은 이 템플릿 태그에서 사용되는 템플릿의 내용입니다.

{% for advert in adverts %}
    <p>
        <a href="{{ advert.url }}">
            {{ advert.text }}
        </a>
    </p>
{% endfor %}

그런 다음 자체 페이지 템플릿에서 스니펫 템플릿 태그를 포함할 수 있습니다.

{% load wagtailcore_tags demo_tags %}

...

{% block content %}

    ...

    {% adverts %}

{% endblock %}

페이지에 스니펫 바인딩

위 예시에서 광고 목록은 페이지의 다른 콘텐츠와 독립적으로 사용자 지정 템플릿 태그를 통해 표시되는 고정 목록입니다. 이는 사이드바의 일반적인 패널에 대해 원하는 것일 수 있지만, 다른 시나리오에서는 특정 페이지에 스니펫의 특정 인스턴스 하나만 표시하고 싶을 수 있습니다. 이는 페이지 모델 내에 스니펫 모델에 대한 외래 키를 정의하고 페이지의 content_panels 목록에 FieldPanel 을 추가하여 달성할 수 있습니다. 예를 들어, BookPage 인스턴스에 특정 광고를 표시하려면:

  # ...
  class BookPage(Page):
      advert = models.ForeignKey(
          'demo.Advert',
          null=True,
          blank=True,
          on_delete=models.SET_NULL,
          related_name='+'
      )

      content_panels = Page.content_panels + [
          FieldPanel('advert'),
          # ...
      ]

스니펫은 템플릿에서 page.advert 로 액세스할 수 있습니다.

페이지에 여러 광고를 첨부하려면 FieldPanelBookPage 자체 대신 BookPage 의 인라인 자식 객체에 배치할 수 있습니다. 여기서는 이 자식 모델을 BookPageAdvertPlacement 라고 합니다(BookPage에 광고가 배치될 때마다 이러한 객체가 하나씩 있기 때문).

from django.db import models

from wagtail.models import Page, Orderable

from modelcluster.fields import ParentalKey

# ...

class BookPageAdvertPlacement(Orderable, models.Model):
    page = ParentalKey('demo.BookPage', on_delete=models.CASCADE, related_name='advert_placements')
    advert = models.ForeignKey('demo.Advert', on_delete=models.CASCADE, related_name='+')

    class Meta(Orderable.Meta):
        verbose_name = "광고 배치"
        verbose_name_plural = "광고 배치"

    panels = [
        FieldPanel('advert'),
    ]

    def __str__(self):
        return self.page.title + " -> " + self.advert.text


class BookPage(Page):
    # ...

    content_panels = Page.content_panels + [
        InlinePanel('advert_placements', label="광고"),
        # ...
    ]

이러한 자식 객체는 이제 페이지의 advert_placements 속성을 통해 액세스할 수 있으며, 거기에서 연결된 Advert 스니펫을 advert 로 액세스할 수 있습니다. BookPage 의 템플릿에는 다음이 포함될 수 있습니다.

{% for advert_placement in page.advert_placements.all %}
    <p>
        <a href="{{ advert_placement.advert.url }}">
            {{ advert_placement.advert.text }}
        </a>
    </p>
{% endfor %}