본문 바로가기

문돌이 존버/Django 스터디

장고(Django), Form Validation

반응형
본 글은 Holix의 "리액트와 함께 장고 시작하기 Complete" 강의를 듣고 작성한 일지입니다.

이번 시간엔 Form 유효성 검사에 대해 자세히 알아보겠습니다.

먼저 Form 유효성 검사는 .is_valid() 함수에서 수행되며, 유효성 검사 호출 로직은 아래와 같습니다.

1. form.full_clean() 호출
- 각 필드 객체별: 각 필드객체.clean() 호출을 통해 각 필드 타입에 맞춰 유효성 검사
- Form 객체 내: 필드 이름 별로 Form 객체.clean_필드명() 함수가 있다면 호출해서 유효성 검사
                     Form객체.clean() 함수가 있다면 호출해서 유효성 검사(필드 다수를 묶어서 검사할 필요가 있을                                                                                             경우)

2. 에러 유무에 따른 True/False 리턴

Form에서는 2가지 유효성 검사를 수행합니다.

1. Validator 함수를 통한 유효성 검사
- 값이 원하는 조건에 맞지 않을 때 ValidationError 예외 발생
- 리턴값은 사용되지 않음

2. Form 클래스 내 clean, clean_ 멤버함수를 통한 유효성 검사 및 값 변경
- 값이 원하는 조건에 맞지 않을 때 ValidationError 예외 발생
- 리턴값을 통해 값 반환
# forms.py
from django import forms
from .models import Post

import re

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = [
            'content', 'photo', 'tag_set', 'is_public'
        ]

    # content 필드 예시
    def clean_content(self):
        content = self.cleaned_data.get('content')
        if content:
            content = re.sub(r'[a-zA-Z]+', '', content) # 영어는 모두 제거
        return content

영어로 ahew... 를 타이핑했지만 아래 결과에선 영어가 삭제된 것을 확인할 수 있습니다.

Validators는 함수형과 클래스형으로 나뉘어서 어떤 형태로든 모두 커스텀으로 만드는 것이 가능합니다. 다만 빌트인 Validators(RegexValidator, EmailValidator, URLValidator, MaxValueValidator 등)를 최대한 활용하는 것을 추천합니다.

모델 필드에 디폴트로 적용된 validators는 아래와 같습니다.

models.EmailField
- validators.validate_email 적용

models.URLField
- validators.URLValidator 적용

models.GenericIPAddressField
- validators.ip_address_validators 적용

models.SlugField
- validators.validate_slug 적용

 Form clean 멤버함수의 역할은 2가지로 정리할 수 있습니다.

1. "필드별 Error 기록" 또는 "Non 필드 Error 기록"
- 값이 조건에 안 맞으면 ValidationError 예외를 통해 오류 기록
- add_error(필드명, 오류내용) 직접 호출을 통해 오류 기록
2. 원하는 포맷으로 값 변경
- 리턴값을 통해 값 변경

필드별 Error / Non 필드 Error 기록에 대해 조금 더 살펴보겠습니다.

clean_필드명() 멤버함수
- 특정 필드별 검사/변경의 책임
- ValidationError 예외 발생 시, 해당 필드 Error로 분류

clean() 멤버함수
- 다수 필드에 대한 검사/변경의 책임
- ValidationError 예외 발생 시, non_field_errors로 분류
- add_error() 함수를 통해 필드별 Error 기록도 가능

그렇다면 언제 validators를 사용하고, 언제 clean을 사용할까요?

validators
- 지속적인 유효성 검사 루틴이 필요할 때
- 가급적 모든 validators는 모델에 정의하고(Fat Model), ModelForm을 통해 모델의 validators 정보도 같이 가져오기

clean
- 특정 Form에서 1회성 유효성 검사 루틴이 필요할 때
- 다수 필드값에 걸쳐서 유효성 검사가 필요할 때
- 필드값을 변경할 필요가 있을 때

마지막으로 게임에서 서버와 닉네임을 선택할 때 유니크함을 체크하는 예제 코드를 소개드리겠습니다.

# models.py
from django.core.validators import MinLengthValidator

class GameUser(models.Model):
    server = models.CharField(max_length=10)
    username = models.CharField(max_length=20, validators=[MinLengthValidator(3)]
    
    # DB에서 server-username 합쳐서 유니크함 확인
    class Meta:
        # 장고에서 제공하는 기본 탬플릿
        unique_together = [
            ('server', 'username')
        ]

# forms.py
class GameUserSignupForm(forms.ModelForm):
    class Meta:
        model = GameUser
        fields = ['server', 'username']
728x90
반응형