(streamfield_validation)= # StreamField 유효성 검사 모든 StreamField 블록은 블록 값을 받아 정리된 버전의 값을 반환하거나, 값이 유효성 검사에 실패하면 `ValidationError` 를 발생시키는 `clean` 메서드를 구현합니다. URLBlock 값이 올바르게 형식화된 URL인지 확인하는 것과 같은 내장 유효성 검사 규칙은 이 메서드를 통해 구현됩니다. 또한 StructBlock과 같이 다른 블록의 컨테이너 역할을 하는 블록의 경우, `clean` 메서드는 자식 블록의 `clean` 메서드를 재귀적으로 호출하고 필요에 따라 호출자에게 유효성 검사 오류를 다시 발생시키는 것을 처리합니다. `clean` 메서드는 사용자 지정 유효성 검사 로직을 구현하기 위해 블록 서브클래스에서 재정의할 수 있습니다. 예를 들어, 자식 블록 중 하나를 채워야 하는 StructBlock은 다음과 같이 구현할 수 있습니다. ```python from django.core.exceptions import ValidationError from wagtail.blocks import StructBlock, PageChooserBlock, URLBlock class LinkBlock(StructBlock): page = PageChooserBlock(required=False) url = URLBlock(required=False) def clean(self, value): result = super().clean(value) if not(result['page'] or result['url']): raise ValidationError("페이지 또는 URL 중 하나를 지정해야 합니다.") return result ``` ```{note} `StreamField` 의 블록 유효성 검사는 모델 필드(`wagtail.fields.StreamField`)가 아닌 폼 필드(`wagtail.blocks.base.BlockField`)를 통해 이루어집니다. 이는 페이지 인스턴스에서 유효성 검사 메서드(`my_page.full_clean()` 등)를 호출해도 `StreamField` 데이터의 유효하지 않은 블록을 잡아내지 못한다는 의미입니다. 이는 `StreamField` 의 데이터가 폼 필드 이외의 다른 경로를 통해 프로그래밍 방식으로 추가될 때만 관련이 있습니다. ``` ## 오류 메시지 렌더링 위치 제어 위 예제에서는 `ValidationError` 유형의 예외가 발생하여 StructBlock 전체에 오류가 첨부되고 렌더링됩니다. 오류가 나타나는 위치를 더 세밀하게 제어하려면 `wagtail.blocks.StructBlockValidationError` 예외 클래스를 대신 발생시킬 수 있습니다. 이 클래스의 생성자는 다음 인수를 받습니다. - `non_block_errors` - StructBlock 전체에 대해 발생시킬 오류 메시지 또는 `ValidationError` 인스턴스 목록 - `block_errors` - StructBlock의 특정 자식 블록에 대해 표시할 `ValidationError` 인스턴스 사전으로, 키는 자식 블록의 이름입니다. 다음 예제는 StructBlock 내의 'description' 블록에 첨부된 유효성 검사 오류를 발생시키는 것을 보여줍니다. ```python from django.core.exceptions import ValidationError from wagtail.blocks import CharBlock, StructBlock, StructBlockValidationError, TextBlock class TopicBlock(StructBlock): keyword = CharBlock() description = TextBlock() def clean(self, value): result = super().clean(value) if result["keyword"] not in result["description"]: raise StructBlockValidationError(block_errors={ "description": ValidationError("설명에는 키워드가 포함되어야 합니다.") }) return result ``` ListBlock과 StreamBlock도 유사하게 작동하는 해당 예외 클래스 `wagtail.blocks.ListBlockValidationError` 및 `wagtail.blocks.StreamBlockValidationError` 를 가지고 있습니다. 단, `block_errors` 사전의 키는 오류를 첨부할 블록의 숫자 인덱스입니다. ```python from django.core.exceptions import ValidationError from wagtail.blocks import ListBlock, ListBlockValidationError class AscendingListBlock(ListBlock): # 사용 예시: # price_list = AscendingListBlock(FloatBlock()) def clean(self, value): result = super().clean(value) errors = {} for i in range(1, len(result)): if result[i] < result[i - 1]: errors[i] = ValidationError("값은 오름차순이어야 합니다.") if errors: raise ListBlockValidationError(block_errors=errors) return result ```