Lina's Toolbox

Django Form 본문

 

 

✔️ 기능이 많은(독선적) 프레임워크일수록 처음 러닝커브가 가파른편입니다.
이 구간만 지나면 훨씬 평이해지니 화이팅! 

오늘 내용도 외우려고 하지 말고,
이런게 있구나만 알고 넘어가는 마음가짐으로 하기를 바란다.

장고 폼클래스는 선택의 영역이다!
커스텀할 코드가 많다면 그냥 html 써도됨.
변경해줄 부분이 많지 않다면, 장고폼을 쓰면 더 편할뿐..!

 

Django Form Class

Django Form Class로 반복 작업을 줄여줄 수 있다.


유저는 사악하다?!

숫자만 입력하세요: 히히히히히
⇒ 숫자만 입력하라고 되어있지만, 꼭 다른 형식으로 입력하시는 분들이 있습니다.
  • 그렇기 때문에, 유저가 입력하는 데이터는 반드시 유효성 검사가 필요합니다!
       이 과정에서 중복되는 코드도 많겠죠?
    
    ⇒ 그러면 form도 작성해야지, view도 작성해야지, 유효성 검사도 해야지
  • django는 일부 반복되는 작업과 코드를 줄일 수 있는 django form을 제공합니다.→ 직접 구현한 Form + View로직이 필요하다면 사용하지 않아도 괜찮아요!
  • → 하지만 항상 Django Form을 사용할 필요는 없어요!

 

실습

1. Form 선언하기

articles/forms.py

from django import forms


class ArticleForm(forms.Form):
    title = forms.CharField(max_length=10)
    content = forms.CharField()
  • 모델과 구조가 매우 비슷하다!  
  • Model 선언과 비슷하게 내가 이 Form에서 입력받고자 하는 데이터에 대한 명세를 작성합니다.
  • → 형식이나 속성도 일부 Model과 비슷해요. (모델 처럼 상속도 해준다!!)

models.py 보면서 작성해주자.

(db와 길이제한, 데이터 타입 등이 다르면 안되겠죠?)

 

forms에도 이 데이터를 어디로 보낼지에 대한 정보는 없죠?

→ 따라서 form 태그는 내가 꼭 작성해주어야합니다!

 

2. Form 적용하기

  • 새 글 작성에 적용하기 (new)
    articles/new.html
...
{{ form.as_p }}
...

template에서 변수를 사용했다 == view에서 넘겨줬다!

(forms도 view에서 넘겨줘야한다.)

 

 

articles/views.py

from.forms import ArticleForm
...
def new(request):
	form = ArticleForm()
	context = {
		"form": form,
	}
	return render(request, "new.html", context)
...

content 입력이 더 큼지막했으면 좋겠는데..?

→ input 보여주는 것을 수정하고 싶다면?

→ 폼 위젯 사용!

→ forms에서 매개변수로 

→ 공식문서 참조

 

Form rendering options

✔️ 공식문서
https://docs.djangoproject.com/en/4.2/topics/forms/#form-rendering-options
  • label과 input을 랜더링하는것에 대한 옵션
    • as_div : <div>로 감싸져서 렌더링됩니다.
    • as_p : <p>로 감싸져서 렌더링됩니다.

 

Form Widget

✔️ 공식문서
https://docs.djangoproject.com/en/4.2/topics/forms/#widgets
  • 페이지에서 Form Input 요소가 어떻게 렌더링 되어서 보여질지 정의합니다.
  • Form Fields에 할당해서 사용합니다.

=> <input type=”text”> 에 썼던 거예요!!

 

사용해보기

  • articles/forms.py (text field)

 

articles/forms.py (choice field)

주제 선정 (셀렉트 필드)를 만들고 싶다면?

→ 초이스 필드

 


Django Model Form

ModelForm Clas는 알아서 Model을 참조해 Form을 만들어줍니다.

 

Django ModelForm Class

🤔 그런데 Django Form 사용하다보니까 Model과 너무 유사하게 쓰게 된다는 생각이 드시죠? 그러면 Django가 알아서 Model을 참조해 Model Field를 보고 Form을 만들어주면 더 좋을 것 같지않나요!?
✔️ 공식문서
https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/#modelform

 

 

Model을 통해서 Form Class를 만드는 방식

articles/forms.py

from django import forms

from articles.models import Article


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = "__all__"
        # exclude = ["title"]
  • ModelForm이 사용할 데이터를 Meta 클래스에 명시합니다.
  • fields 항목에 내가 form으로 만들고 싶은 항목들을 지정할 수 있습니다.

어떤 모델을 참조할 지 : 메타 클래스(class Meta)

 fields =[]에는

1. 내가 입력받고 싶은 필드들을 나열해주거나

2 ="__all__"라고 적어줘서 모든 필드를 입력받게 하고,

3. exclude =[] 로 제외하고 싶은 필드를 적어줘도 된다.

created_at, updated_at 는 알아서 값이 들어가서 exclude안 써줘도 잘 동작한다.

 

 

Django Model Form이 제공해주는 여러 편의성

  • Django의 Form은 기본적인 유효성 검사 등을 처리합니다.

view에서 Django ModelForm 사용하기

articles/views.py

...
def create(request):
  form = ArticleForm(request.POST) # form에 request.POST에 있는 데이터 채워
  if form.is_valid(): # form 형식에 맞으면
      article = form.save() # 저장하고 해당 객체 반환 
      return redirect("article_detail", article.id)
  return redirect("new")
...

이게 가능한 이유? Model을 알고 있기 때문 !

form = ArticleForm(request.POST)

내가 작성한 데이터로 채워진 폼 : 데이터가 "바인딩" 된 폼이다.

 

form.is_valid()

→ is_valid 함수: 입력된 데이터들이 모델에 정의된 필드값들과의 유효성 검사를 만족한다면!

 

🤔 조금 더 생각해보기

현재의 new 함수와 create 함수가 많이 흡사해요!
def new(request):
    form = ArticleForm()
    context = {
        "form": form,
    }
    return render(request, "new.html", context)​

 

⇒ 그냥 create 함수 하나로 처리할 수 없을까요?
GET으로 들어오면 비어있는 Form 보여주고,
POST로 들어오면 데이터 채워서 보낸거니까 새로운 article 생성하면 되지 않을까요?

⇒ GET/POST방식으로 나눠서, 하나의 함수로 처리해보자.

 

 

new - create 수정하기

articles/views.py

def create(request):
  if request.method == "POST":
      form = ArticleForm(request.POST)
      if form.is_valid():
          article = form.save()
          return redirect("article_detail", article.id)
  else:
      form = ArticleForm()

  context = {"form": form}
  return render(request, "create.html", context)

처음부터 이렇게 코딩할 수 있는 사람은 없어요. 구조에 익숙해지는 것이 필요해요.

 

이제 new 라는 구조가 필요없습니다!

  • new view 함수 지우기
  • new url path 지우기
  • new.htmlcreate.html 로 변경
{% extends "base.html" %}


{% block content %}
<h1>New Article</h1>

<form action="{% url 'create' %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">저장</button>
</form>
{% endblock content %}

create.html (전 new.html)

 

articles.html 에서 새 글 작성을 create 로 변경

 

 


 

edit - update 수정하기

  • edit과 update도 마찬가지로 아래의 로직으로 처리가 가능
    • GET으로 수정하기에 요청이 들어오면, 데이터 채운 Form을 랜더링해서 보여줘요!
    • POST로 수정하기에 요청이 들어오면, 새로운 데이터가 들어오는거니까 수정으로 처리해요!

 

구현하기

update view 함수

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

→ Model Form은 instance라는 속성에 값이 있으면 해당 instance를 수정하고 값이 없으면 새로 생성하는 로직을 수행합니다.

모델폼은 아무런 데이터도 안들어오면(instance속성의 값이 비어있으면), 새로운 데이터를 생성한다! (create)

instance = article 처럼 인스턴스에 조회한 값을 넣어주면 (save하면) 이 article(instance)를 수정한다!  (update)

 

ArticleForm = (insatance=article) 해주면 article의 데이터로  폼이채워지게

 

  • 마찬가지로 이제 edit 구조가 필요없습니다.
    • edit view를 지우기
    • edit url path 지우기
    • edit.htmlupdate.html로 변경
{% extends "base.html" %}

{% block content %}
<h1>Update Article</h1>

<form action="{% url 'update' article.pk %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">수정</button>
</form>

<a href="{% url 'article_detail' article.pk %}">이전으로</a>
{% endblock content %}

update.html (전 edit.html)

 

 

  • article_detail.html 에서 글 수정 버튼 변경
  • → 기존 edit이었던 부분을 update 로 수정합니다.

 

→ 이렇게 장고를 쓰니 블럭처럼 코드가 깔끔해졌죠?!

 


장고모델폼 쓸 줄 알아야합니다!

모델폼을 사용하기 싫다구요? 그냥 html로 작성하고싶다구요?
그래도 됩니다! 그렇게도 많이 씁니다.

하지만 모델폼도 많이 사용됩니다.

그렇기 때문에 보고 읽을 줄은 알아야하겠죠?

바로 그것이 우리가 장고 모델폼을 알아야하는 이유입니다.