스니펫 렌더링¶
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 로 액세스할 수 있습니다.
페이지에 여러 광고를 첨부하려면 FieldPanel 을 BookPage 자체 대신 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 %}