레시피¶
serve() 메서드 재정의¶
Wagtail은 Page 에서 파생된 모델을 모델 이름과 일치하는 Django HTML 템플릿에 페이지 객체에 대한 참조를 전달하여 제공하는 것을 기본으로 하지만, HTML 이외의 것을 제공하고 싶다면 어떻게 해야 할까요? Page 클래스에서 제공하는 serve() 메서드를 재정의하고 Django 요청 및 응답을 더 직접적으로 처리할 수 있습니다.
EventPage 객체의 다음 예시를 고려해 봅시다. 이 객체는 요청에 format 변수가 설정된 경우 iCal 파일로 제공됩니다.
class EventPage(Page):
...
def serve(self, request):
if "format" in request.GET:
if request.GET['format'] == 'ical':
# ical 형식으로 내보내기
response = HttpResponse(
export_event(self, 'ical'),
content_type='text/calendar',
)
response['Content-Disposition'] = 'attachment; filename=' + self.slug + '.ics'
return response
else:
# 인식할 수 없는 형식 오류
message = '이벤트를 내보낼 수 없습니다.\n\n인식할 수 없는 형식: ' + request.GET['format']
return HttpResponse(message, content_type='text/plain')
else:
# 평소와 같이 이벤트 페이지 표시
return super().serve(request)
serve() 는 Django 요청 객체를 받아 Django 응답 객체를 반환합니다. Wagtail은 템플릿과 생성하는 컨텍스트를 포함하는 TemplateResponse 객체를 반환하며, 이는 미들웨어가 의도한 대로 작동하도록 합니다. 따라서 HttpResponse 와 같은 더 간단한 응답 객체는 이러한 이점을 얻지 못한다는 점을 명심하십시오.
이 전략을 사용하면 Django 또는 Python 유틸리티를 사용하여 모델을 JSON 또는 XML 또는 원하는 다른 형식으로 렌더링할 수 있습니다.
사용자 지정 route() 메서드로 엔드포인트 추가¶
참고
페이지에 더 많은 엔드포인트를 추가하는 훨씬 더 간단한 방법은 RoutablePageMixin 믹스인에서 제공합니다.
Wagtail은 경로 구성 요소(슬래시 / 로 구분됨)를 반복하고, 슬러그를 기반으로 일치하는 객체를 찾고, 해당 객체의 모델 클래스에 추가 라우팅을 위임하여 요청을 라우팅합니다. Wagtail 소스는 어떤 일이 발생하는지 파악하는 데 매우 유용합니다. 다음은 Page 클래스의 기본 route() 메서드입니다.
class Page(...):
...
def route(self, request, path_components):
if path_components:
# 요청은 이 페이지의 자식에 대한 것입니다.
child_slug = path_components[0]
remaining_components = path_components[1:]
# 일치하는 자식을 찾거나 404
try:
subpage = self.get_children().get(slug=child_slug)
except Page.DoesNotExist:
raise Http404
# 추가 라우팅 위임
return subpage.specific.route(request, remaining_components)
else:
# 요청은 이 페이지 자체에 대한 것입니다.
if self.live:
# 이 페이지의 serve() 메서드를 호출하도록 Wagtail에 알리는 RouteResult 반환
return RouteResult(self)
else:
# 페이지가 요청과 일치하지만 게시되지 않았으므로 404
raise Http404
route() 는 현재 객체(self), request 객체, 그리고 요청 URL에서 남은 path_components 목록을 받습니다. Wagtail 트리에서 자식 중 하나에 대해 route() 를 다시 호출하여 라우팅을 계속 위임하거나, RouteResult 객체를 반환하거나 404 오류를 발생시켜 라우팅 프로세스를 종료합니다.
route() 메서드를 재정의하여 Wagtail 트리에서 각 객체에 대한 사용자 지정 엔드포인트를 만들 수 있습니다. 한 가지 사용 사례는 경로에서 print/ 엔드포인트를 만날 때 대체 템플릿을 사용하는 것입니다. 다른 사용 사례는 현재 객체와 상호 작용하는 REST API일 수 있습니다. 어떤 일이 발생하는지 확인하기 위해 모든 자식 경로 구성 요소를 인쇄하는 간단한 모델을 만들어 보겠습니다.
먼저 models.py:
from django.shortcuts import render
from wagtail.url_routing import RouteResult
from django.http.response import Http404
from wagtail.models import Page
# ...
class Echoer(Page):
def route(self, request, path_components):
if path_components:
# Wagtail에 self.serve()를 추가 'path_components' kwarg와 함께 호출하도록 알립니다.
return RouteResult(self, kwargs={'path_components': path_components})
else:
if self.live:
# Wagtail에 self.serve()를 추가 인수 없이 호출하도록 알립니다.
return RouteResult(self)
else:
raise Http404
def serve(self, path_components=[]):
return render(request, self.template, {
'page': self,
'echo': ' '.join(path_components),
})
이 모델 Echoer 는 속성을 정의하지 않지만 Page 를 서브클래스하므로 객체는 사용자 지정 제목과 슬러그를 가질 수 있습니다. 템플릿은 {{ echo }} 속성을 표시하기만 하면 됩니다.
이제 Wagtail 관리자에서 “Echo Base”라는 새 Echoer 페이지를 만든 후 다음과 같은 요청은:
http://127.0.0.1:8000/echo-base/tauntaun/kennel/bed/and/breakfast/
다음을 반환합니다.
tauntaun kennel bed and breakfast
serve() 메서드에 새로운 필수 인수를 도입하는 경우 주의하십시오. Wagtail은 미리 보기 및 중재를 위해 페이지의 기본 뷰를 계속 표시할 수 있어야 하며, 기본적으로 요청 객체와 추가 인수 없이 serve() 를 호출하여 이 작업을 수행하려고 시도합니다. serve() 메서드가 이를 메서드 시그니처로 허용하지 않으면 페이지의 serve_preview() 메서드를 재정의하여 적절한 인수로 serve() 를 호출해야 합니다.
def serve_preview(self, request, mode_name):
return self.serve(request, variant='radiant')