이론

트리 소개

트리를 추상 데이터 유형으로 잘 모르는 경우 관련 개념을 검토하는 것이 좋습니다.

그러나 웹 개발자로서 파일 시스템 디렉터리 또는 경로와 같은 트리에 대한 좋은 이해를 이미 가지고 있을 것입니다. Wagtail 페이지는 다음과 같이 각 페이지가 자체 URL 경로를 갖는 동일한 구조를 만들 수 있습니다.

/
    people/
        nien-nunb/
        laura-roslin/
    events/
        captain-picard-day/
        winter-wrap-up/

Wagtail 관리 인터페이스는 트리를 사용하여 편집을 위한 콘텐츠를 구성하고, 탐색기 메뉴를 통해 트리에서 위아래로 레벨을 탐색할 수 있도록 합니다. 이 구성 방법은 자체 Wagtail 모델을 생각할 때 시작하기에 좋은 곳입니다.

노드와 리프

만들려는 Page 파생 모델을 두 가지 노드 유형 중 하나인 부모와 리프로 생각하는 것이 편리할 수 있습니다. Wagtail은 이 접근 방식에 대해 규정하지 않지만, 자체 콘텐츠 유형을 구성하는 데 경험이 없는 경우 시작하기에 좋은 곳입니다.

노드

Wagtail 트리의 부모 노드는 아마도 자손의 탐색 가능한 색인을 구성하고 표시하기를 원할 것입니다. 예를 들어 블로그는 개별 게시물 목록을 표시하는 방법이 필요합니다.

부모 노드는 자손 객체의 탐색 가능한 색인을 반환하는 자체 함수를 제공할 수 있습니다.

class EventPageIndex(Page):
    # ...
    def events(self):
        # 이 페이지의 자손인 라이브 이벤트 페이지 목록 가져오기
        events = EventPage.objects.live().descendant_of(self)

        # 현재 실행 중이거나 미래에 시작하는 이벤트를 필터링
        events = events.filter(date_from__gte=date.today())

        # 날짜별로 정렬
        events = events.order_by('date_from')

        return events

이 예시는 반환된 객체를 Wagtail의 관리 인터페이스를 통해 게시된 콘텐츠(live()) 및 이 노드의 자식(descendant_of(self))으로 제한하여 의미 있는 콘텐츠만 반환하도록 합니다. 모델에서 subpage_types 클래스 속성을 설정하여 자식으로 설정할 수 있는 모델을 지정할 수 있으며, parent_page_types 클래스 속성을 설정하여 이 페이지 모델의 부모가 될 수 있는 모델을 지정할 수 있습니다. Wagtail은 기본적으로 모든 Page 파생 모델을 허용합니다. 그럼에도 불구하고 부모 모델이 의미 있는 필터링된 색인을 제공하는 것이 좋습니다.

리프

리프는 콘텐츠 자체, 즉 소비 가능한 페이지이며, 단순히 속성 묶음으로 구성될 수 있습니다. 블로그 페이지 리프에는 본문 텍스트와 이미지가 있을 수 있습니다. 사람의 페이지 리프에는 사진, 이름 및 주소가 있을 수 있습니다.

리프가 트리에서 부모로 돌아가는 방법을 제공하는 것이 도움이 될 수 있습니다. 예를 들어, 브레드크럼 탐색의 경우입니다. 트리도 리프의 부모가 일반 사이트 탐색에 포함되지 않을 정도로 깊을 수 있습니다.

리프에 대한 모델은 트리를 반대 방향으로 탐색하고 적절한 조상을 반환하는 함수를 제공할 수 있습니다.

class EventPage(Page):
    # ...
    def event_index(self):
        # 가장 가까운 이벤트 색인인 조상 찾기
        return self.get_ancestors().type(EventIndexPage).last()

정의된 경우 subpage_typesparent_page_types 도 리프를 포함할 수 있는 부모 모델을 제한합니다. 그렇지 않으면 Wagtail은 Wagtail 트리에서 부모와 리프의 모든 조합을 허용합니다. 색인 페이지와 마찬가지로 색인이 실제로 리프를 포함할 것으로 예상되는 모델인지 확인하는 것이 좋습니다.

기타 관계

Page 파생 모델은 기본 Wagtail 트리를 확장하거나 완전히 벗어나는 다른 상호 관계를 가질 수 있습니다. 형제 간 탐색을 위한 함수를 제공할 수 있습니다. 예를 들어 블로그 페이지의 “다음 게시물” 링크(post->post->post)와 같습니다. 하위 트리가 상호 관련되는 것도 의미가 있을 수 있습니다. 예를 들어 토론 포럼(forum->post->replies)과 같습니다. 계층 구조를 건너뛰는 것도 의미가 있을 수 있습니다. 예를 들어 특정 모델 클래스의 모든 객체가 조상과 관계없이 상호 관련되는 경우(events = EventPage.objects.all)와 같습니다. 모델이 상호 관계를 정의하는 것은 주로 모델에 달려 있으며, 가능성은 무한합니다.

Wagtail 요청의 해부

모델 정의 및 상호 관계의 기본을 넘어설 때 Wagtail이 요청을 처리하고 응답을 구성하는 방법을 아는 것이 도움이 될 수 있습니다. 간단히 말해서 다음과 같습니다.

  1. Django가 요청을 받고 Wagtail의 URL 디스패처 정의를 통해 라우팅합니다.

  2. Wagtail은 요청의 호스트 이름을 확인하여 어떤 Site 레코드가 이 요청을 처리할지 결정합니다.

  3. 해당 사이트의 루트 페이지부터 시작하여 Wagtail은 페이지 트리를 탐색하고 route() 메서드를 호출하며 각 페이지 모델이 요청을 직접 처리할지 또는 자식 페이지로 전달할지 결정하도록 합니다.

  4. 요청을 처리하는 페이지는 route() 에서 RouteResult 객체를 반환하며, 이는 페이지와 serve() 에 전달될 추가 args/kwargs 를 식별합니다.

  5. Wagtail은 serve() 를 호출하고, serve()get_context() 를 사용하여 컨텍스트를 구성합니다.

  6. serve()get_template() 을 사용하여 전달할 템플릿을 찾습니다.

  7. serve() 에서 응답 객체가 반환되고 Django는 요청자에게 응답합니다.

자체 모델에서 Page 클래스 메서드(예: route()serve())를 재정의하여 이 프로세스에 사용자 지정 동작을 적용할 수 있습니다. 예시는 레시피를 참조하십시오.

예약된 게시

페이지 게시물은 편집 페이지의 상태 사이드 패널에 있는 일정 설정 기능을 통해 예약할 수 있습니다. 이를 통해 초기 페이지 게시 또는 페이지 업데이트를 미리 설정할 수 있습니다. 예약된 시간에 페이지가 라이브로 전환되려면 publish_scheduled 관리 명령을 설정해야 합니다.

예약된 게시의 기본 워크플로

  • 예약은 페이지의 게시 예정 필드를 설정하고 _게시_를 클릭하여 수행됩니다.

  • 현재 라이브 상태가 아닌 페이지에 대한 개정을 예약하면 예약된 시간이 되면 해당 페이지가 라이브로 전환됩니다.

  • 이미 라이브 상태인 페이지에 대한 개정을 예약하면 예약된 시간이 되면 해당 개정이 게시됩니다.

  • 페이지에 예약된 개정이 있고 다른 개정을 즉시 게시하도록 설정하면(즉, 게시 예정 필드를 설정하지 않고 _게시_를 클릭하면) 예약된 개정은 예약 취소됩니다.

  • 페이지에 예약된 개정이 있고 다른 개정을 게시하도록 예약하면(즉, 게시 예정 필드를 설정하고 _게시_를 클릭하면) 기존 예약된 개정은 예약 취소되고 새 개정이 대신 예약됩니다.

참고

개정이 예약되려면 게시 예정 필드를 설정한 후 _게시_를 클릭해야 합니다. 게시 예정 필드를 설정하고 _게시_를 클릭하지 않고 초안 개정을 저장하면 게시되도록 예약되지 않습니다.

예약된 개정 보기 및 관리

주어진 페이지의 기록 뷰는 어떤 개정이 예약되었는지, 언제 예약되었는지 보여줍니다. 목록의 예약된 개정은 취소할 수 있는 예약 취소 버튼도 제공합니다.

예약된 게시 취소

페이지를 게시하도록 예약하는 것 외에도 만료 필드를 설정하여 페이지를 게시 취소하도록 예약할 수도 있습니다. 그러나 게시와 달리 게시 취소 일정은 특정 개정 대신 라이브 페이지 인스턴스에 적용됩니다. 즉, 만료 필드에 대한 모든 변경 사항은 관련 개정이 게시된 후에만 적용됩니다(즉, 변경 사항이 라이브 인스턴스에 적용될 때). 예를 들어:

예약된 게시 취소의 기본 워크플로

  • 예약은 페이지의 만료 필드를 설정하고 _게시_를 클릭하여 수행됩니다. 게시 예정 필드도 설정된 경우 게시 취소 일정은 개정이 라이브로 전환된 후에만 적용됩니다.

  • 예를 들어 6월 14일에 게시 취소되도록 예약된 라이브 페이지가 있다고 가정해 봅시다. 그런 다음 일정 전에 새 개정이 게시 취소 일정보다 이른 날짜(예: 6월 9일)에 게시되도록 예약되었다고 가정해 봅시다. 새 개정이 6월 9일에 라이브로 전환되면 새 개정에 포함된 만료 필드가 기존 게시 취소 일정을 대체합니다. 즉:

    • 새 개정에 다른 만료 필드(예: 6월 17일)가 포함된 경우 새 개정은 6월 9일에 라이브로 전환되고 페이지는 6월 14일에 게시 취소되지 않고 6월 17일에 게시 취소됩니다.

    • 새 개정에 만료 필드가 설정되지 않은 경우 새 개정은 6월 9일에 라이브로 전환되고 게시 취소 일정은 해제되므로 페이지는 게시 취소되지 않습니다.

  • 예를 들어 6월 14일에 게시 취소되도록 예약된 다른 라이브 페이지가 있다고 가정해 봅시다. 그런 다음 일정 전에 새 개정이 게시 취소 일정보다 늦은 날짜(예: 6월 21일)에 게시되도록 예약되었다고 가정해 봅시다. 새 개정은 6월 21일에 라이브로 전환될 때까지 적용되지 않으므로 페이지는 여전히 6월 14일에 게시 취소됩니다. 즉:

    • 새 개정에 다른 만료 필드(예: 6월 25일)가 포함된 경우 페이지는 6월 14일에 게시 취소되고 새 개정은 6월 21일에 라이브로 전환되며 페이지는 6월 25일에 다시 게시 취소됩니다.

    • 새 개정에 만료 필드가 설정되지 않은 경우 페이지는 6월 14일에 게시 취소되고 새 개정은 6월 21일에 라이브로 전환됩니다.

참고

동일한 예약 메커니즘은 DraftStateMixin 이 적용된 스니펫에도 적용됩니다. 자세한 내용은 스니펫 초안 변경 사항 저장를 참조하십시오.