django

CRUD를 위한 ModelForm

발전생 2020. 12. 19. 15:22

CRUD 중 Create, Update, Delete를 위해서는 제출할 수 있는 Form이 필요하다.

<form action="" method="">
	<label></label>
	<input>
    <label></label>
    <input>
    <input type="submit" value="submit"">
</form>

일반적으로 이러한 구조를 가지는 템플릿이 필요하다. (Delete는 별도의 input 태그가 안 필요할 수도 있지만)

 

Django에는 일반 Form도 있지만 ModelForm도 존재한다.

일반 form class를 만들어서 사용하면 form에서 사용할 field들을 다 새로 정의해 줘야 하는 불편함이 있다.

이 불편함을 해결하고자 ModelForm이 존재한다.

ModelForm에서는 사용하는 Model의 field들을 가져다가 사용할 수 있다. Data와의 연동성이 향상된다. 코드 양도 줄어든다.

 

forms.py를 app level에 만들어주고 사용하면 된다. 

from django.forms import ModelForm
from .models import *

class MyForm(ModelForm):
    class Meta:
        model = #사용하는 model 이름
        fields = '__all__'

이렇게 하면 MyForm은 정해준 model과 그 model의 모든 field를 사용하는 form을 만들어 준다. 

 

fields = ['field1', 'field2'] 

이런 식으로 필요한 fields만 form에 나타나도록 정의해줄 수 도 있다. 하지만 django 공식 문서에서는 

fields = '__all__'
exclude = ['field3', 'field4']

이 두 가지를 사용할 것을 권장한다. fields에 리스트를 전달하는 건 보안상 문제가 있다고 해석이 된다.

 

정의해 준 form을 views.py에서 템플릿에 매개변수로 넘겨준 뒤 템플릿에서 form을 필요한 부분에 끼워넣어서 rendering하면 된다.

 

주의할 점이 있다.

"form"을 넣어서 클래스를 정의했지만 전달되는 건 <label> tag와 <input> tag뿐이다. 따라서 겉을 싸는 <form> 태그와 <input type="submit value="submit"> 태그는 템플릿에서 별도로 만들어 줘야 한다.

 


views.py에서

Create

order_form.html에 접속하면 request.method == 'GET'이다.

else에 해당하므로 빈 form을 만들고 order_form.html에 매개변수로 전달해준다.

빈 form이기 때문에 input 태그에 기본적으로 아무것도 입력이 안 되어있다.

 

만약 order_form.html에서 submit 버튼을 눌러서 request.method == 'POST'라면 if에 해당하므로 request.POST를 보고 Form을 채운다.

(max_length를 넘었거나 email field에 이메일 양식을 안 적었다면 에러 발생)

form이 이상이 없다면 form.save()를 실행한다.

form.save()를 하면 form에 있던 POST 내용을 바탕으로 데이터베이스에 모델 인스턴스를 새로 만들고 저장한다.

그리고나서 home url로 돌아간다. 이 처리를 안 하면 사용자가 제출이 안 된 줄 알고 중복 제출을 할 수 있다.

만약 form에 이상이 있다면(에러가 존재) render() 함수가 호출된다. 그러면 웹 브라우저에는 이전에 적었던 내용이 적힌 form이 템플릿과 함께 뜬다. django가 기본적으로 제공해주는 기능 덕분에 이상이 있는 input 위에 뭐가 잘못됐는지 알려준다.

 

Update

Create와 거의 유사한 구조를 가진다.

주목할 만한 차이점은 Create에서보다 Form에 매개변수가 하나씩 더 있다는 것이다. 이 점이 Create와 Update를 분별할 수 있는 부분이다.

Create는 그저 form에 제출된 대로 새로 인스턴스를 만들어서 데이터베이스에 저장하면 된다.

그러나 Update는 기존 데이터베이스에 있던 인스턴스를 가져와서 갱신을 해준다.

그렇기 때문에 order = Order.objects.get(id=pk) 로 update 해줄 인스턴스를 가져온다. 

form의 매개변수에 instance=order 를 추가로 넣어줘서 인스턴스를 참고하게 한다.

form.save()를 호출하면 update에서는 매개변수로 넣어준 instance를 갱신한 뒤 데이터베이스에 저장한다.

 

Delete

Delete는 간단히 "삭제 확인"에 해당하는 POST 요청이 오면 해당 인스턴스를 데이터베이스에서 지운다.

 


직접 작성한 form을 상속

 

form을 정의했는데 약간의 변경이 필요하다면 상속해서 사용할 수 있다.

주의 할 점이라면 class Meta 부분에서도 상속을 명시해줘야 한다는 점이다.

 


참고 자료

https://www.youtube.com/watch?v=EX6Tt-ZW0so&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=11

 

'django' 카테고리의 다른 글

회원가입, 로그인, 로그아웃  (0) 2020.12.20
여러 개의 form을 만들어주는 formset  (0) 2020.12.19
model 관계(데이터베이스)  (0) 2020.12.18
model을 만들면 해줘야 하는 일  (0) 2020.12.17
django url pattern  (0) 2020.12.17