본문 바로가기
Python

Django formset, is_valid 란 무엇인가?

by Shark_상어 2023. 4. 22.
728x90

이 글은 formset, is_valid 에 대한 공부 및 정리 목적으로 쓰는 글이다.

 

1. formset 이란 무엇인가?

여러개의 폼을 한번에 처리 하는데 사용 된다.

Formset은 동일한 폼 클래스를 사용하여 여러 개의 인스턴스를 생성하고, 이 들을 한번에 처리하고 저장 하도록 도와준다.

 

ex) 여러개의 댓글을 동시에 작성 하거나, 한번에 여러개의 파일을 업로드 할 경, Formset를 이용 하면 된다.

 

# forms.py
from django import forms
from django.forms import formset_factory
from .models import Comment

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('name', 'email', 'message')

CommentFormSet = formset_factory(CommentForm, extra=3) # 최대 3개의 댓글을 작성할 수 있는 Formset을 생성한.


# views.py
from django.shortcuts import render
from .forms import CommentFormSet

def add_comment(request):
    if request.method == 'POST':
        formset = CommentFormSet(request.POST)
        if formset.is_valid():
            formset.save() # 모든 댓글을 한 번에 저장합니다.
    else:
        formset = CommentFormSet()
    return render(request, 'add_comment.html', {'formset': formset})


# add_comment.html
<form method="post">
    {% csrf_token %}
    {{ formset.management_form }}
    {% for form in formset %}
        {{ form.as_p }}
    {% endfor %}
    <button type="submit">저장하기</button>
</form>

 

2. is_valid() 이란 무엇인가?

사용자가 제출한 데이터가 유효한지 여부를 검증 한다.

이 메서드는 사용자 입력 데이터를 유효성 검사하고, 검증에 실패한 필드에 대한 오류를 포함한 폼 에러를 생성한다.

 

is_valid() 들은 많은 하위 함수들을 호출 하여 작동하는 함수이다.

 

하위 함수 들은 이렇게 존재 한다.

 

1. full_clean(): is_valid() 가 호출 되면 먼저 full_clean() 메서드가 호출 되고, 이 메서드 에서는 폼의 각 필드에 대해

clean() 메서드 와 clean_<fieldname>() 메서드를 차례로 호출 한다.

 

full_clean() 메서드는 ValidationError 예외를 발생 시키고, 이러한 예외는 폼의 에러 리스트에 추가 한다.

 

2. clean(): clean() 메서드는 전체 폼에 대한  유효성 검사를 수행한다.

이 메서드는 폼의 모든 필드에 대해 유효성 검사를 수행하고, 모든 필드에서 통과한 후에만 폼 전체에서 통과한다.

이 메서드는 일반적으로 여러 필드를 조합 하여 검증 규칙을 정의하고 필드 간의 관계를 검사한다.

 

예를 들면 이러한 코드이다.

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        email = cleaned_data.get('email')
        message = cleaned_data.get('message')

        if not name and not email and not message:
            raise forms.ValidationError('You have to write something!')

 

위의 코드에서 clean() 메서드는  'name', 'email', 'message' 필드를 검사 하고, 이들 필드 중 하나 라도 입력 되지 않았을때

ValidationError 예외를 발생 시킨다.

 

3. clean_<fieldname>(): clean_<fieldname>() 메서드는 특정 필드에 대한 유효성 검사를 수행 한다.

이 메서드는 해당 필드에서 유효성 검사를 수행 하며, 필드에서 통과한 경우 cleaned_data 딕셔너리에 저장 된다.

이 메서드는 필드 별 검 증 규칙을 정의 할 수 있다.

 

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean_name(self):
        name = self.cleaned_data.get('name')
        if name == 'Admin':
            raise forms.ValidationError("Admin is not a valid name.")
        return name

 

위의 코드에 'cleaned_name()` 메서드는 'name' 필드를 검사하고, 입력된 값이 admin 일 경우 ValidationError 예외를 발생 시키고, 만약 검증에 통과한다면, 해당 필의 값이 'cleaned_data' 딕셔너리에 저장 된다.

 

4. validate_unique(): 'validate_unique()' 메서드는 모델 폼에서 사용 되고, 이  메서드는 모델 에서 고유한 필드를 검증 한다.

즉, 중복 검사를 실시 한다고 보면 된다.

 

5. has_error(fieldname): 이 메서드는 특정 필드에 대한 에러 여부를 확인한다. 에러가 존재하면 True, 반대 라면 False를 반환 한다.

 

6. errors: 이 속성은 폼에서 발생한 모든 에러를 담고 있는 딕셔너리 이다. 딕셔너리 의 각 키는 에러가 발생한 필드 이름,

값은 에러 메시지 리스트 이다.

 

is_valid()가 False로 반환된 코드상에서 print(form.errors()) 하면 보일 것이다.

 

7.'non_field_errors()': 이 메서드는 필드와 관련되지 않은 모든 에러 메시지를 리스트로 반환 한다.

clean() 메서드에서 발생한 에러는 이 메서드를 통해 확인 할수 있다.

 

8. add_error(field, error): 이 메서드는 특정 필드에 대한 에러 메시지를 추가 한다.

필드 와 에러메시지를 인수로 전달 해야 한다.

 

ex)

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        email = cleaned_data.get('email')
        message = cleaned_data.get('message')

        if not name:
            self.add_error('name', '이름을 입력해주세요.')
        if not email:
            self.add_error('email', '이메일을 입력해주세요.')
        if not message:
            self.add_error('message', '메시지를 입력해주세요.')

form = ContactForm(data={'name': '', 'email': '', 'message': ''})
form.is_valid()
print(form.errors)

{'name': ['이름을 입력해주세요.'], 'email': ['이메일을 입력해주세요.'], 'message': ['메시지를 입력해주세요.']}

9. add_waring(field, warning): 이 메서드는 특정 필드 에 대한 경고 메시지를 추가 하는 메서드 이다.

필드 와 경고 메시지를 인수로 전달 해야 하며, 경고 메시지는 에러 메시지와 달리, 폼 유효성 검사를 실패하지 않도록 허용 한다.

 

ex)

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean(self):
        cleaned_data = super().clean()
        message = cleaned_data.get('message')

        if message and len(message) < 10:
            self.add_warning('message', '메시지가 너무 짧습니다.')

form = ContactForm(data={'name': '홍길동', 'email': 'hong@example.com', 'message': '안녕하세요.'})
form.is_valid()
form.add_warning('name', '이름이 너무 짧습니다.')
print(form.errors)
print(form.warnings)

{}
{'name': ['이름이 너무 짧습니다.'], 'message': ['메시지가 너무 짧습니다.']}
728x90