[Django] ModelForm

Jin·2021년 9월 12일
0

django

목록 보기
6/14
post-thumbnail

ModelForm

Model이 있고 사용자가 게시글을 제출할 수 있는 양식을 만들고 싶은 경우 이미 모델에서 필드를 정의 했기에 form에서 필드를 재정의 하는 중복된 행위를 방지 하기 위해 Django는 Model을 통해 Form Class를 만들 수 있는 Helper 제공



ModelForm Class

  • Model을 통해 Form Class를 만들 수 있는 Helper
  • 일반 Form Class와 완전히 같은 방식(객체 생성)으로 view에서 사용 가능

1. ModelForm 선언하기

  • forms 라이브러리에서 파생된 ModelForm 클래스 상속받음
  • 정의한 클래스 안에 Meta 클래스를 선언, 어떤 모델을 기반으로 form을 작성할 것인가에 대한 정보를 Meta Class에 지정

2. Meta Class

  • Model의 정보를 작성하는 곳
  • ModelForm을 사용할 경우 사용할 모델이 있어야하는데 Meta class가 이를 구성
    • 해당 model에 정의한 field 정보를 Form에 적용하기 위함
    • 몇개만 사용하고 싶다면 list나 tuple형식으로 작성하면 됨
    • 하지만 너무 많은것 중 몇개만 제외 하고 싶다면 exclude 사용
# 타이틀 필드 제외
class Meta : 
	model = Article
  fields = '__all__'
  exclude = ('title')

3. is_valid & save()

is_valid() method

  • 유효성 검사를 실행하고, 데이터가 유효한지 여부를 boolean으로 반환

save() method

  • form에 바인딩 된 데이터에서 데이터베이스 객체를 만들고 저장
  • ModelForm의 하위(sub)클래스는 기존 모델 인스턴스를 키워드 인자 instance로 받아 들일 수 있다.
    • 이게 제공 되면 save()는 해당 인스턴스를 업데이트(update)
    • 제공되지 않으면 save()는 지정된 모델의 새 인스턴스를 만듦(create)
  • form의 유효성이 확인되지 않은경우 save()를 호출하면 form.errors를 확인하여 에러 확인 가능
def create(request):
	if request.method == 'POST':
    		form = ArticleForm(request.POSt) # Query dict를 첫번째 인자로 받음 -> 데이터가 채워진 form이 만들어짐
    # 유효성 검사
    		if form.is_valid():
    			article = form.save()  # 새로 작성된 객체 article
        # detail 페이지로 이동하기 위해 article객체를 생성한것이지 무조건 해야 되는건 아님. 만약 index 페이지로 redirect할꺼면 객체 생성 필요 없이 그냥 form.save()만 하면 된다.
        	return redirect('articles:detail', article.pk)
        
    	else:
        # new
        	form = ArticleForm()
        context = {
        	'form' : form,
        }
        
	return render(request, 'articles/new.html', context)
     
# 기존에 있는 데이터를 수정할 경우

def update(request,pk):
    article = Article.objects.get(pk=pk)
    if request.method == 'POST':
    	form = ArticleForm(request.POST, instance=article)
        if form.is_valid():
            form.save()
    	    return redirect('articles:detail', article.pk)
    
    else:
    	form = Article.Form(instance=article)
    context = {
    	'form' : form,
        }
    return render(request, 'articles/update.html', context)

위의 코드에서 context가 else와 동일 선상에 있는이유

  1. 만약 context와 return이 else안에 있을경우 if form.is_valid()가 False라면 실행이 될 코드가 없음.
  1. 유효성 검사를 실패 했을때 form이 context안에 form으로 들어옴. 그냥 들어오는게 아니라 is_ method의 특성상 유효성 검사를 통과 하지 못했을 때 통과 하지못한 에러 메시지를 담아서 내려 보내줌.
  2. new의 상황에서는 빈 form을 만들기만 하면 됨.

request.method가 post인지 먼저 확인하는 이유

  1. 만약 GET을 먼저 검사하고 else처리를 해버리면 여기서는 POST가 아니라 PUT, PATCH, DELETE 등 다른 메서드로 요청이 와도 실행이 된다는 문제가 생긴다.
  1. GET을 먼저 분기했을때 불필요한 반복 생김

3. Widgets 적용하기

class ArticleForm(forms.ModelForm):
	title = forms.CharField(
   		label = 'title',
        	widget = forms.TextInput(
            		attrs={
                    		'class' : 'my-title',
                            	'placeholder' : 'Enter the title',
                           }
                ),
       )
      
      class Meta:
      	model = Article:
        fields = '__all__'
        
        

Form과 ModelForm 의 차이

  • Form
    • 어떤 model에 저장해야 하는지 알 수 없으므로 유효성 검사 이후 cleaned_data딕셔너리를 생성
    • cleaned_data 딕셔너리에서 데이터를 가져온 후 .save()를 호출해야함
    • model에 연관되지 않은 데이터를 받을 때 사용
  • ModelForm
    • django가 해당 model에서 양식에 필요한 대부분의 정보를 이미 정의
    • 어떤 레코드를 만들어야 할 지 알고 있으므로 바로 .save() 호출 가능
profile
내가 다시 볼려고 작성하는 블로그. 아직 열심히 공부중입니다 잘못된 내용이 있으면 댓글로 지적 부탁드립니다.

0개의 댓글