Django model form is_valid() saves instance automatically

Reading time ~2 minutes


modelform의 form.is_valid() 메서드는 내부적으로 여러가지 일을 하는데 그 중에 하나는 Model Form의 데이터를 폼 인스턴스로 알아서 저장하는 것이다. 이 때 is_valid() 가 True인지 False인지 와는 관계가 없다.


views.py

def edit_post(request, post_id):
    post = Post.objects.get(id=post_id)

    if request.method == 'POST':
        post_form = PostForm(request.POST, instance=post)
        print(post.title) # 1.
        if post_form.is_valid():
            print(post.title) # 2.
            [...]
        else
            print(post.title) # 3.
            [...]

Post를 수정하는 view이다. 2.3.에서 기존의 post의 title 값을 기대하고 작업을 했는데 실제로는 reqeust.POST[‘title’]의 값이 출력된다. 1. 에서는 수정하기 전의 title 값을 출력한다. 그 이유는 위에서 언급했듯이 is_valid() 메서드에서 post 인스턴스의 값을 request.POST에 들어있는 값으로 자동으로 설정하기 때문이다.


>>> Post.objects.create(title='origin title', content='content')
>>> post = Post.objects.get(id=1)
>>> form = PostForm({'title': 'edited title'}, instance=post)
>>> post.title
u'origin title'
>>> form.is_valid()
True
>>> post.title
u'edited title'
>>> post2 = Post.objects.get(id=1)  # DB로 부터 새로운 instance를 가져온다
>>> post2.title                     # DB의 title 값이 그대로이다.
u'origin title'
>>> form.save()                     # DB에 form데이터를 저장한다
>>> post3 = Post.objects.get(id=1)  # 다시 DB로 부터 새로운 instance를 가져온다
>>> post3.title                     # DB의 title 값이 변경되어있다.
u'edited title'

python shell로 간단히 테스트해 본 결과이다.

is_valid() 를 호출하면 post instance에 form의 값들이 저장되지만 DB에 저장되는 것은 아니다. (post2으로 확인) save()함수를 호출하면 DB에 저장된다. (post3으로 확인)


is_valid() 에서 유효성 검사의 성공 여부와 관계없이 form 데이터가 항상 instance에 저장되는 것을 상기하면서 활용하면 좋을 것 같다. 위의 예시 코드로 예를 들어보면, 유효성 검사에 실패했을 경우 사용자가 입력한 form의 데이터(post)와 실제 DB의 모델 instance(post3) 의 데이터를 따로 비교, 저장 할 수 있다.


참고자료

Two Scoops of Django - 대니얼 로이 그린팰드, 오드리 로이 그린펠드 지음 / 김승진 옮김

Django file upload 기능 구현하기 - Model Form 이용

djanog에서 file upload 기능을 구현하는데 modelform을 이용하였더니 편리하게 구현할 수 있었다. 그 과정에 대한 포스팅이다.MEDIA Settingupload file은 MEDIA_ROOT에 저장이 되고, 요청할 때는 ME...… Continue reading