(api_v2_configuration)= # Wagtail API v2 설정 가이드 이 문서 섹션에서는 Wagtail 사이트에 대한 공개 API를 설정하는 방법을 보여줍니다. API가 Django REST Framework를 기반으로 구축되었지만 Wagtail의 종속성이므로 수동으로 설치할 필요가 없습니다. ## 기본 설정 ### 앱 활성화 먼저 Django가 볼 수 있도록 Wagtail의 API 앱을 활성화해야 합니다. Django 프로젝트 설정의 `INSTALLED_APPS` 에 `wagtail.api.v2` 를 추가합니다. ```python # settings.py INSTALLED_APPS = [ ... 'wagtail.api.v2', ... ] ``` 선택적으로 `rest_framework` 를 `INSTALLED_APPS` 에 추가할 수도 있습니다. 이렇게 하면 웹 브라우저에서 볼 때 API를 탐색할 수 있지만 기본 JSON 형식 출력에는 필요하지 않습니다. (api_v2_configure_endpoints)= ### 엔드포인트 구성 다음으로 API에 노출할 콘텐츠를 구성할 차례입니다. 각 콘텐츠 유형(예: 페이지, 이미지 및 문서)에는 자체 엔드포인트가 있습니다. 엔드포인트는 라우터에 의해 결합되며, 라우터는 나머지 프로젝트에 연결할 수 있는 URL 구성을 제공합니다. Wagtail은 사용할 수 있는 여러 엔드포인트 클래스를 제공합니다. - 페이지 `wagtail.api.v2.views.PagesAPIViewSet` - 이미지 `wagtail.images.api.v2.views.ImagesAPIViewSet` - 문서 `wagtail.documents.api.v2.views.DocumentsAPIViewSet` - 리디렉션 `wagtail.contrib.redirects.api.RedirectsAPIViewSet` [](redirects_api_endpoint) 참조 이러한 엔드포인트 클래스 중 하나를 서브클래싱하여 기능을 사용자 정의할 수 있습니다. 예를 들어, 이 경우 원하는 렌더러 클래스를 설정하여 `APIViewSet` 을 변경해야 하는 경우: ```python from rest_framework.renderers import JSONRenderer # ... class CustomPagesAPIViewSet(PagesAPIViewSet): renderer_classes = [JSONRenderer] name = "pages" api_router.register_endpoint("pages", CustomPagesAPIViewSet) ``` 또는 페이지 결과에 사용할 원하는 모델을 변경합니다. ```python 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를 만듭니다. ```python # 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을 등록합니다. ```python # 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/` 에서 사용할 수 있습니다. (apiv2_page_fields_configuration)= ### 사용자 정의 페이지 필드 추가 API를 통해 일부 사용자 정의 필드를 내보내야 할 가능성이 높습니다. 이는 각 페이지 모델에 대해 `api_fields` 속성에 내보낼 필드 목록을 추가하여 수행할 수 있습니다. 예를 들어: ```python # 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 자체의 매개변수](apiv2_custom_page_fields)를 사용하여 `blog.BlogPage` 유형을 선택해야 합니다. (form_page_fields_api_field)= ### API에 양식 필드 추가 `FormPage` 라는 FormBuilder 페이지가 있는 경우 API에 양식 필드를 노출하는 방법의 예는 다음과 같습니다. ```python from wagtail.api import APIField class FormPage(AbstractEmailForm): #... api_fields = [ APIField('form_fields'), ] ``` ### 사용자 정의 직렬 변환기 [직렬 변환기](https://www.django-rest-framework.org/api-guide/fields/)는 모델의 데이터베이스 표현을 JSON 형식으로 변환하는 데 사용됩니다. `serializer` 키워드 인수를 사용하여 모든 필드의 직렬 변환기를 재정의할 수 있습니다. ```python 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](https://www.django-rest-framework.org/api-guide/fields/#source) 인수를 사용할 수 있으므로 다른 필드 이름을 갖거나 기본 필드가 전혀 없는 API 필드를 추가할 수 있습니다. ```python 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에 두 개의 필드가 추가됩니다(간결성을 위해 다른 필드는 생략됨). ```json { "published_date": "2017-04-06", "published_date_display": "Thursday 06 April 2017" } ``` ### API의 리치 텍스트 위의 예에서 우리는 [](../../../extending/rich_text_internals)에 설명된 리치 텍스트에 대한 Wagtail의 저장소 형식을 사용하여 `body` 필드를 직렬화합니다. 이는 API 클라이언트가 리치 텍스트 내의 외부 데이터를 참조하는 식별자를 직접 조작할 때(예: 페이지 링크 또는 이미지에 대한 자세한 데이터를 ID로 가져올 때) 유용합니다. 또한 API가 `|richtext` 템플릿 필터와 유사하게 "표시" 표현을 직접 제공하는 것도 종종 유용합니다. 이는 사용자 정의 직렬 변환기를 사용하여 수행할 수 있습니다. ```python 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` 가 이 새 직렬 변환기를 사용하도록 할 수 있습니다. ```python APIField('body', serializer=RichTextSerializer()), ``` (api_v2_images)= ### API의 이미지 `ImageRenditionField` 직렬 변환기를 사용하면 이미지의 변환을 API에 추가할 수 있습니다. 이미지에서 수행할 크기 조정 작업을 지정하는 이미지 필터 문자열이 필요합니다. 위에서 설명한 `source` 키워드 인수도 사용할 수 있습니다. 예를 들어: ```python 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에 다음이 추가됩니다. ```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_images)에 대한 설명서 참조). ### 인증 API에 대한 액세스를 보호하기 위해 Django REST Framework에서 제공하는 [인증](https://www.django-rest-framework.org/api-guide/authentication/) 방법(예: [토큰 인증](https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication))을 구현할 수 있습니다. ```python # api.py from rest_framework.permissions import IsAuthenticated # ... class CustomPagesAPIViewSet(PagesAPIViewSet): name = "pages" permission_classes = (IsAuthenticated,) api_router.register_endpoint("pages", CustomPagesAPIViewSet) ``` 설정을 확장합니다. ```python # 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` 쿼리 매개변수](apiv2_pagination)와 결합하십시오.