점프투장고 3-09 질문 수정에서 ModelForm 개념 질문

[pybo/views.py]

@login_required(login_url='common:login')
def question_modify(request, question_id):
    """
    pybo 질문수정
    """
    question = get_object_or_404(Question, pk=question_id)
    if request.user != question.author:
        messages.error(request, '수정권한이 없습니다')
        return redirect('pybo:detail', question_id=question.id)

    if request.method == "POST":
        form = QuestionForm(request.POST, instance=question)
        if form.is_valid():
            question = form.save(commit=False)
            question.modify_date = timezone.now()  # 수정일시 저장
            question.save()
            return redirect('pybo:detail', question_id=question.id)
    else:
        form = QuestionForm(instance=question)
    context = {'form': form}
    return render(request, 'pybo/question_form.html', context)

[pybo/forms.py]

class QuestionForm(forms.ModelForm):
    class Meta:
        model = Question  # 사용할 모델
        fields = ['subject', 'content']  # QuestionForm에서 사용할 Question 모델의 속성
        labels = {
            'subject': '제목',
            'content': '내용',
        }

form = QuestionForm(request.POST, instance=question)에서 instance=question을 제외했더니 Question의 author와 create_date 속성이 null이어서 에러가 났습니다. 원래 예상에는 QuestionForm의 인스턴스인 form에는 클래스 선언대로 subject와 content 속성만 저장되었다고 생각했기에 이상함을 느껴 질문 남깁니다. (이전 챕터 질문 생성 코드에서, form.save(commit=True)를 썼을 때 create_date 속성이 비어있어 에러가 났었기 때문에)

혹시 ModelForm을 정의하면, fields에 Model의 모든 속성을 집어넣지 않아도 자동으로 모든 속성의 값을 저장하고 있는 것인가요? 이때 html <form>을 통해서는 fields에 정의된 속성들을 입력받는다고 생각했는데 맞는지 궁금합니다.

참고로 [pybo/views.py]의 if문을 아래와 같이 수정했더니 에러가 나진 않았지만 기존 질문이 수정되는 대신 새로운 질문 인스턴스가 생성되는 것을 확인했습니다. (생성일시에는 임의로 현재시각을 저장했습니다.)

    if request.method == "POST":
        form = QuestionForm(request.POST)
        if form.is_valid():
            question = form.save(commit=False)  # 기존 질문을 기준으로 폼을 생성하지 않음
            question.author = request.user  # author 속성에 로그인 계정 저장
            question.create_date = timezone.now()  # create_date 속성에 현재일시 저장
            question.modify_date = timezone.now()  # 수정일시 저장
            question.save()
            return redirect('pybo:detail', question_id=question.id)

steven3391 450

M 2021년 12월 29일 11:08 오후

목록으로
1개의 답변이 있습니다. 1 / 1 Page

form.save 실행시 form에 있는 값을 이용하여 model 데이터를 저장합니다. 이때 오류가 나는 이유는 폼에서 나는것이 아니라 model 에서 납니다.모델 데이터를 저장하려고 할때 create_date와 같은 값이 없기 때문입니다.

박응용

2021년 12월 29일 11:27 오후

늦은 밤 답변 감사합니다. 추가로 제 이해가 맞는지 궁금하여 여쭤보고자 합니다. form에 있는 값을 이용하여 model 데이터를 저장한다면, [pybo/views.py]에서 아래와 같은 코드가 작동하는 것은 form 객체에 question의 author와 create_date 정보가 저장되어 있다고 보는 것이 맞나요?? question = form.save(commit=False) question.modify_date = timezone.now() # 수정일시 저장 question.save() . - steven3391님, M 2021년 12월 29일 11:53 오후 추천 , 대댓글
+1 @steven3391님 question = form.save(commit=False) 에서 돌려받은 question은 폼이 아니라 모델입니다. 따라서 form 객체와는 상관이 없습니다. - 박응용님, 2021년 12월 30일 12:33 오전 추천 , 대댓글
@박응용님 말씀 듣고 찾아보니 modelform 생성 시 instance 매개변수가 주어지는지 여부에 따라 save 메서드 호출 시에 모델 인스턴스를 업데이트 하거나 새로 생성한다고 나오네요. (https://docs.djangoproject.com/ko/4.0/topics/forms/modelforms/#the-save-method) 이해가 된 것 같습니다. 도움 주셔서 감사합니다. - steven3391님, M 2021년 12월 30일 1:12 오전 추천 , 대댓글