Wagtail API v2 설정 가이드¶
이 문서 섹션에서는 Wagtail 사이트에 대한 공개 API를 설정하는 방법을 보여줍니다.
API가 Django REST Framework를 기반으로 구축되었지만 Wagtail의 종속성이므로 수동으로 설치할 필요가 없습니다.
기본 설정¶
앱 활성화¶
먼저 Django가 볼 수 있도록 Wagtail의 API 앱을 활성화해야 합니다.
Django 프로젝트 설정의 INSTALLED_APPS 에 wagtail.api.v2 를 추가합니다.
# settings.py
INSTALLED_APPS = [
...
'wagtail.api.v2',
...
]
선택적으로 rest_framework 를 INSTALLED_APPS 에 추가할 수도 있습니다.
이렇게 하면 웹 브라우저에서 볼 때 API를 탐색할 수 있지만 기본 JSON 형식 출력에는 필요하지 않습니다.
엔드포인트 구성¶
다음으로 API에 노출할 콘텐츠를 구성할 차례입니다. 각 콘텐츠 유형(예: 페이지, 이미지 및 문서)에는 자체 엔드포인트가 있습니다. 엔드포인트는 라우터에 의해 결합되며, 라우터는 나머지 프로젝트에 연결할 수 있는 URL 구성을 제공합니다.
Wagtail은 사용할 수 있는 여러 엔드포인트 클래스를 제공합니다.
페이지
wagtail.api.v2.views.PagesAPIViewSet이미지
wagtail.images.api.v2.views.ImagesAPIViewSet문서
wagtail.documents.api.v2.views.DocumentsAPIViewSet리디렉션
wagtail.contrib.redirects.api.RedirectsAPIViewSetAPI 참조
이러한 엔드포인트 클래스 중 하나를 서브클래싱하여 기능을 사용자 정의할 수 있습니다.
예를 들어, 이 경우 원하는 렌더러 클래스를 설정하여 APIViewSet 을 변경해야 하는 경우:
from rest_framework.renderers import JSONRenderer
# ...
class CustomPagesAPIViewSet(PagesAPIViewSet):
renderer_classes = [JSONRenderer]
name = "pages"
api_router.register_endpoint("pages", CustomPagesAPIViewSet)
또는 페이지 결과에 사용할 원하는 모델을 변경합니다.
from rest_framework.renderers import JSONRenderer
# ...
class PostPagesAPIViewSet(PagesAPIViewSet):
model = models.BlogPage
api_router.register_endpoint("posts", PostPagesAPIViewSet)
또한 API에 다른 콘텐츠 유형을 추가하는 데 사용할 수 있는 기본 엔드포인트 클래스가 있습니다. wagtail.api.v2.views.BaseAPIViewSet
이 예에서는 기본 구성에 세 가지 내장 콘텐츠 유형을 모두 포함하는 API를 만듭니다.
# api.py
from wagtail.api.v2.views import PagesAPIViewSet
from wagtail.api.v2.router import WagtailAPIRouter
from wagtail.images.api.v2.views import ImagesAPIViewSet
from wagtail.documents.api.v2.views import DocumentsAPIViewSet
# 라우터를 만듭니다. "wagtailapi"는 URL 네임스페이스입니다.
api_router = WagtailAPIRouter('wagtailapi')
# "register_endpoint" 메서드를 사용하여 세 개의 엔드포인트를 추가합니다.
# 첫 번째 매개변수는 엔드포인트의 이름(예: 페이지, 이미지)입니다. 이것은
# 엔드포인트의 URL에 사용됩니다.
# 두 번째 매개변수는 요청을 처리하는 엔드포인트 클래스입니다.
api_router.register_endpoint('pages', PagesAPIViewSet)
api_router.register_endpoint('images', ImagesAPIViewSet)
api_router.register_endpoint('documents', DocumentsAPIViewSet)
다음으로 Django가 요청을 API로 라우팅할 수 있도록 URL을 등록합니다.
# urls.py
from .api import api_router
urlpatterns = [
...
path('api/v2/', api_router.urls),
...
# api_router 라인이 기본 Wagtail 페이지 제공 경로 위에 오도록 합니다.
re_path(r'^', include(wagtail_urls)),
]
이 구성을 사용하면 페이지는 /api/v2/pages/, 이미지는 /api/v2/images/, 문서는 /api/v2/documents/ 에서 사용할 수 있습니다.
사용자 정의 페이지 필드 추가¶
API를 통해 일부 사용자 정의 필드를 내보내야 할 가능성이 높습니다. 이는 각 페이지 모델에 대해 api_fields 속성에 내보낼 필드 목록을 추가하여 수행할 수 있습니다.
예를 들어:
# blog/models.py
from wagtail.api import APIField
class BlogPageAuthor(Orderable):
page = models.ForeignKey('blog.BlogPage', on_delete=models.CASCADE, related_name='authors')
name = models.CharField(max_length=255)
api_fields = [
APIField('name'),
]
class BlogPage(Page):
published_date = models.DateTimeField()
body = RichTextField()
feed_image = models.ForeignKey('wagtailimages.Image', on_delete=models.SET_NULL, null=True, ...)
private_field = models.CharField(max_length=255)
# API를 통해 필드 내보내기
api_fields = [
APIField('published_date'),
APIField('body'),
APIField('feed_image'),
APIField('authors'), # 이렇게 하면 관련 BlogPageAuthor 객체가 API 응답에 중첩됩니다.
]
이렇게 하면 published_date, body, feed_image 및 name 필드가 있는 authors 목록을 API에서 사용할 수 있습니다. 그러나 이러한 필드에 액세스하려면 ?type API 자체의 매개변수를 사용하여 blog.BlogPage 유형을 선택해야 합니다.
API에 양식 필드 추가¶
FormPage 라는 FormBuilder 페이지가 있는 경우 API에 양식 필드를 노출하는 방법의 예는 다음과 같습니다.
from wagtail.api import APIField
class FormPage(AbstractEmailForm):
#...
api_fields = [
APIField('form_fields'),
]
사용자 정의 직렬 변환기¶
직렬 변환기는 모델의 데이터베이스 표현을 JSON 형식으로 변환하는 데 사용됩니다. serializer 키워드 인수를 사용하여 모든 필드의 직렬 변환기를 재정의할 수 있습니다.
from rest_framework.fields import DateField
class BlogPage(Page):
...
api_fields = [
# published_date 필드의 형식을 "Thursday 06 April 2017"로 변경
APIField('published_date', serializer=DateField(format='%A %d %B %Y')),
...
]
Django REST 프레임워크의 직렬 변환기는 모두 source 인수를 사용할 수 있으므로 다른 필드 이름을 갖거나 기본 필드가 전혀 없는 API 필드를 추가할 수 있습니다.
from rest_framework.fields import DateField
class BlogPage(Page):
...
api_fields = [
# ISO8601 형식의 날짜(기본값)
APIField('published_date'),
# 다른 형식의 별도 published_date_display 필드
APIField('published_date_display', serializer=DateField(format='%A %d %B %Y', source='published_date')),
...
]
이렇게 하면 API에 두 개의 필드가 추가됩니다(간결성을 위해 다른 필드는 생략됨).
{
"published_date": "2017-04-06",
"published_date_display": "Thursday 06 April 2017"
}
API의 리치 텍스트¶
위의 예에서 우리는 리치 텍스트 내부에 설명된 리치 텍스트에 대한 Wagtail의 저장소 형식을 사용하여 body 필드를 직렬화합니다. 이는 API 클라이언트가 리치 텍스트 내의 외부 데이터를 참조하는 식별자를 직접 조작할 때(예: 페이지 링크 또는 이미지에 대한 자세한 데이터를 ID로 가져올 때) 유용합니다.
또한 API가 |richtext 템플릿 필터와 유사하게 “표시” 표현을 직접 제공하는 것도 종종 유용합니다. 이는 사용자 정의 직렬 변환기를 사용하여 수행할 수 있습니다.
from rest_framework.fields import CharField
from wagtail.rich_text import expand_db_html
class RichTextSerializer(CharField):
def to_representation(self, instance):
representation = super().to_representation(instance)
return expand_db_html(representation)
그런 다음 api_fields 정의를 변경하여 body 가 이 새 직렬 변환기를 사용하도록 할 수 있습니다.
APIField('body', serializer=RichTextSerializer()),
API의 이미지¶
ImageRenditionField 직렬 변환기를 사용하면 이미지의 변환을 API에 추가할 수 있습니다. 이미지에서 수행할 크기 조정 작업을 지정하는 이미지 필터 문자열이 필요합니다. 위에서 설명한 source 키워드 인수도 사용할 수 있습니다.
예를 들어:
from wagtail.api import APIField
from wagtail.images.api.fields import ImageRenditionField
class BlogPage(Page):
...
api_fields = [
# 원본 이미지에 대한 정보(예: 제목)를 API에 추가합니다.
APIField('feed_image'),
# 렌더링된 이미지 썸네일의 URL을 API에 추가합니다.
APIField('feed_image_thumbnail', serializer=ImageRenditionField('fill-100x100', source='feed_image')),
...
]
이렇게 하면 JSON에 다음이 추가됩니다.
{
"feed_image": {
"id": 45529,
"meta": {
"type": "wagtailimages.Image",
"detail_url": "http://www.example.com/api/v2/images/12/",
"download_url": "/media/images/a_test_image.jpg",
"tags": []
},
"title": "A test image",
"width": 2000,
"height": 1125
},
"feed_image_thumbnail": {
"url": "/media/images/a_test_image.fill-100x100.jpg",
"full_url": "http://www.example.com/media/images/a_test_image.fill-100x100.jpg",
"width": 100,
"height": 100,
"alt": "image alt text"
}
}
참고: download_url 은 원본 업로드된 파일 경로인 반면 feed_image_thumbnail['url'] 은 렌더링된 이미지의 URL입니다. S3와 같은 다른 저장소 백엔드를 사용하는 경우 미디어 파일이 올바르게 구성되어 있으면 download_url 이 이미지에 대한 URL을 반환합니다.
원본 이미지 세트에 SVG가 포함될 수 있는 경우 ImageRenditionField 생성자는 preserve_svg 인수를 사용합니다. preserve_svg 가 True 일 때 ImageRenditionField 의 동작은 image 템플릿 태그의 preserve-svg 인수에 대해 설명된 것과 같습니다(SVG 이미지에 대한 설명서 참조).
인증¶
API에 대한 액세스를 보호하기 위해 Django REST Framework에서 제공하는 인증 방법(예: 토큰 인증)을 구현할 수 있습니다.
# api.py
from rest_framework.permissions import IsAuthenticated
# ...
class CustomPagesAPIViewSet(PagesAPIViewSet):
name = "pages"
permission_classes = (IsAuthenticated,)
api_router.register_endpoint("pages", CustomPagesAPIViewSet)
설정을 확장합니다.
# settings.py
INSTALLED_APPS = [
...
'rest_framework.authtoken',
...
]
...
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.TokenAuthentication"
],
}
앱의 마이그레이션을 실행하는 것을 잊지 마십시오.
API 엔드포인트는 생성된 Token exampleSecretToken123xyz 를 포함하는 Authorization 헤더를 통해서만 액세스할 수 있습니다.
토큰은 Django 관리자의 Auth Token에서 생성하거나 manage.py 명령 drf_create_token 을 사용하여 생성할 수 있습니다.
참고: 프로덕션에서 TokenAuthentication 을 사용하는 경우 API가 https 를 통해서만 사용 가능하도록 해야 합니다.
추가 설정¶
WAGTAILAPI_BASE_URL¶
(프런트엔드 캐시 무효화를 사용할 때 필요)
이것은 문서 파일에 대한 절대 URL을 생성하고 캐시를 무효화할 때 두 곳에서 사용됩니다.
문서에 대한 URL 생성은 이 설정이 설정되지 않은 경우 현재 요청의 호스트 이름으로 대체됩니다. 그러나 캐시 무효화는 이 작업을 수행할 수 없으므로 이 모듈을 wagtailfrontendcache 모듈과 함께 사용할 때 이 설정을 설정해야 합니다.
WAGTAILAPI_SEARCH_ENABLED¶
(기본값: True)
이것을 false로 설정하면 전체 텍스트 검색이 비활성화됩니다. 이것은 모든 엔드포인트에 적용됩니다.
WAGTAILAPI_LIMIT_MAX¶
(기본값: 20)
이를 통해 사용자가 한 번에 요청할 수 있는 최대 결과 수를 변경할 수 있습니다. 이것은 모든 엔드포인트에 적용됩니다. 제한이 없으려면 None 으로 설정하십시오.
원하는 결과 수를 검색하려면 ?limit 및 ?offset 쿼리 매개변수와 결합하십시오.