from wagtail.core.templatetags.wagtailcore_tags import richtext

class RichtextBlock(blocks.RichTextBlock):
    """Richtext without (limited) all the features"""
    
    def get_api_representation(self, value, context=None):
        return richtext(value.source)
    
    class Meta: # noqa
        template = "streams/richtext_block.html"
        icon = "doc-full"
        label = "Full RichText"

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Recaptcha  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing a QuerySet  (0) 2021.11.25
Wagtail API v2 Custom Page Properties  (0) 2021.11.25
Wagtail API v2 Image Rendition Field  (0) 2021.11.24
class BlogChildPagesSerializer(Field):
    def to_representation(self, child_pages):
        # logic in h
        # return_posts = []
        # for child in child_pages:
        #     post_dict = {
        #         'id': child.id,
        #         'title': child.title,
        #         'slug': child.slug,
        #         'url': child.url,
        #     }
        #     return_posts.append(post_dict)
            
        # return return_posts
        return [
            {
                'id': child.id,
                'title': child.title,
                'slug': child.slug,
                'url': child.url,
            } for child in child_pages
        ]


class BlogListingPage(Page):

	...
    
    api_fields = [
        APIField("get_child_pages", serializer=BlogChildPagesSerializer()),
    ]
    
    @property
    def get_child_pages(self):
        return self.get_children().public().live()

기존 class에 없던 데이터나 정보를 API Server에 전달하고 싶을 때에는 Serializer를 사용한다. 다만 단순히 Wagtail의 QuerySet을 전달하면 JSON형식의 데이터가 아니라서 API Server에서 오류가 난다. 

 

그래서 Serializer에서 JSON형식의 데이터를 전달해주기 위해 데이터를 가공을 해줘야한다. 

 

다만, 이미 property에서 field set을 선택하여 return 한다면 Serializer는 필요없다. 

간단한 데이터를 전달할 것이면 아래와 같은 방법으로 전달해도 된다. 

 

class BlogListingPage(Page):
  
    api_fields = [
        APIField("get_child_pages"),
    ]
    
    @property
    def get_child_pages(self):
        return self.get_children().public().live().values("id", "title", "slug")

 

 

추가)

api_fields = [
	APIField("posts", serializer=BlogChildPagesSerializer(source='get_child_pages')),
]

만약에 API Server에 posts라는 이름으로 데이터를 표시하고 싶다면 위와 같이 작성하면 된다. 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25
Wagtail API v2 Custom Page Properties  (0) 2021.11.25
Wagtail API v2 Image Rendition Field  (0) 2021.11.24
Wagtail API v2 Serializers  (0) 2021.11.24
    api_fields = [
    	APIField('a_custom_api_response'),
    ]
    
    @property
    def a_custom_api_response(self):
        #return ["SOMETHING CUSTOM", 3.14, [1, 2, 3, 'a', 'b', 'c']]
        return f"Banner Title Is: {self.banner_title}"

@property를 통해 필요한 Logic이나 정보를 API 서버에 전달할 수 있다. 

저번 포스트에서 Serializer을 통해 Django Models의 이미지를 API서버로 표시하는 방법에 대해서 알아봤다. 

하지만 이미 Wagtail에서는 ImageRenditionField라는 것이 있어 Django Model의 Image를 간단하게 API서버에 

표시할 수 있다. 

 

 

1. Models.py

 

    from wagtail.images.api.fields import ImageRenditionField
    
    
    api_fields = [
        APIField(
            'image', 
            serializer=ImageRenditionField(
                'fill-200x250',                    
                source="author_image"
            )
        ),
    ]

사용 방법은 간단하다. "image"는 API Field에서 보여질 이름이다. 

Django Models의 image field에 API를 적용하여 확인해보면 다음과 같은 오류가 발생한다. 

이럴 때, API에 관련 Field의 정보를 Custom해서 표시해줄 수 있는 Serializer가 필요하다. 

 

from rest_framework.fields import Field


class ImageSerializedField(Field):
    
    def to_representation(self, value):
        return {
            "url": value.file.url,
            "title": value.title,
            "width": value.width,
            "height": value.height,
        }
        
        
class BlogAuthorsOrderable(Orderable):
    
    page = ParentalKey("blog.BlogDetailPage", related_name="blog_authors")
    author = models.ForeignKey(
        "blog.BlogAuthor",
        on_delete=models.CASCADE,
    )
    
    panels = [
        SnippetChooserPanel("author"),
    ]
    
    @property
    def author_image(self):
        return self.author.image
    
    api_fields = [
        APIField('author_image', serializer=ImageSerializedField()),
    ]

Django rest_framework모듈에서 Field을 상속받아서 Serializer를 만든다. 

def to_representation(self, value):

에서의 value는 APIField의 field 값. 즉, 'author_image'(=author.image)를 가르킨다.

 

 

추가)

class BannerCTASerializer(Field):
    def to_representation(self, page):
        return {
            'id': page.id,
            'title': page.title,
            'first_published_at': page.first_published_at,
            'owner': page.owner.username,
            'slug': page.slug,
            'url': page.url,
        }


class HomePage(page):

  api_fields = [
      APIField('banner_cta', serializer=BannerCTASerializer()), 
  ]

Serializer에는 API에 필요한 모든 Logic을 추가할 수 있다.

Wagtail API fields은 정말 간단하고 사용하기 쉽게 되어있다. 다만 Wagtail만의 Model(Page, Orderable..)에서만 사용이 가능하다. 즉, Django models에서는 api_fields를 사용할 수가 없다. 그래서 이번에는 ForeignKey을 사용하는 field에서의 API 적용을 정리한다. 

 

1. Wagtail Models

 

home/models.py

class HomePageCarouselImages(Orderable):
    """Between 1 and 5 images for the home page carousel."""
    
    page = ParentalKey("home.HomePage", related_name="carousel_images")
    carousel_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    
    panels = [
        ImageChooserPanel("carousel_image"),
    ]
    
    api_fields = [
        APIField("carousel_image")
    ]
    

class HomePage(RoutablePageMixin, Page):
    # home page model
    
    ...
    
    content = StreamField(
        [
            ("cta", blocks.CTABlock()),
        ],
        null=True,
        blank=True
    )
    
    api_fields = [
        ...
        APIField('carousel_images'),
        APIField('content'),
    ]

위 코드를 살펴보자. HomePageCarouselImages가 HomePage 모델에 Inline으로 포함되어 있다. 그리고 content는 StreamField이다. 두 모델 전부 Wagtail Model일 경우 간단하게 두 모델에 전부 api_fields를 적어주면 된다. 

 

 

2. Django Models

 

blog/models.py

class BlogAuthorsOrderable(Orderable):
    
    page = ParentalKey("blog.BlogDetailPage", related_name="blog_authors")
    author = models.ForeignKey(
        "blog.BlogAuthor",
        on_delete=models.CASCADE,
    )
    
    panels = [
        SnippetChooserPanel("author"),
    ]
    
    @property
    def author_name(self):
        return self.author.name
    
    @property
    def author_website(self):
        return self.author.website
    
    api_fields = [
        APIField('author_name'),
        APIField('author_website'),
    ]
    
    
class BlogAuthor(models.Model):
    """Blog author for snippets"""
    
    name = models.CharField(max_length=100)
    website = models.URLField(blank=True, null=True)
    
    
class BlogDetailPage(Page):
    """Parental Blog Detail Page"""

	...
    
    content = StreamField(
        [
            ("title_and_text", blocks.TitleAndTextBlock()),
            ("full_richtext", blocks.RichtextBlock()),
            ("simple_richtext", blocks.SimpleRichtextBlock()),
            ("cards", blocks.CardBlock()),
            ("cta", blocks.CTABlock()),
        ],
        null=True,
        blank=True
    )
    
    api_fields = [
        APIField("blog_authors"),
        APIField("content"),
    ]

위와 같은 경우를 살펴보자. BlogAuthorsOrderable와 BlogDetailPage는 Wagtail의 모델인데 BlogAuthor은 Django 모델이다. 이럴경우 BlogAuthor 모델에서는 api_fields를 사용할 수 없다. 

 

그래서 @property를 통해 BlogAuthor 모델을 사용하는 BlogAuthorsOrderable에서 api_fields를 사용해야한다. 

 

    @property
    def author_name(self):
        return self.author.name
    
    @property
    def author_website(self):
        return self.author.website
    
    api_fields = [
        APIField('author_name'),
        APIField('author_website'),
    ]

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail API v2 Image Rendition Field  (0) 2021.11.24
Wagtail API v2 Serializers  (0) 2021.11.24
Wagtail API v2 Fetching Fields  (0) 2021.11.24
Wagtail API v2 Exposing Custom Fields  (0) 2021.11.24
Wagtail API v2 Settings(Headless CMS)  (0) 2021.11.24

+ Recent posts