-
Django Form ClassDjango 2024. 8. 17. 03:13
Django Form Class
일부 반복되는 작업 및 코드를 줄일 수 있는 기능으로 Model과 흡사한 형식으로 진행된다.
→ 폼에 입력받고 싶은 데이터 형식을 정의한 후, 그렇게 정의해놓은 걸 기준으로 자동으로 폼이 생성되게 해준다.
1) Form 선언하기
articles/ forms.py
from django import forms class ArticleForm(forms.Form): title = forms.CharField(max_length=50) content = forms.CharField() # max_lenth를 지정하지 않으면 길이 제한 없게 입력받는 형식이 됨
- Model과 비슷하게 이 Form에서 입력받고자 하는 데이터에 대한 내용을 작성한다.
- 형식이나 속성도 일부 Model과 비슷하다.
2) Form 적용하기
... {{ form.as_p }} ...
현재 new.html 에 기존의 form이 있다.
여기서 우리가 위에서 지정한 제목 title이랑 내용 content 부분을 지워주고
얘로 바꿔주면 됨 → {{ forms.as_p }}
신기🫢
forms는 context로 내용을 받아온거기 때문에 view로 가서 받아올 수 있게 작성해줘야 한다.
views.py 열어서
우리가 만든 클래스 ArticleForm class를 뷰에서 만들어주면 된다.
forms에서 ArticleForm 임포트 해주고
from .forms import ArticleForm
이렇게 forms 가져오고
context에 담아서 인자로 넘겨주면 된다.
서버실행 해보면 잘 나오는 걸 볼 수 있다. 왜 이렇게 감동이지..🥹 ㅎㅎ
근데...🤔
이럴 때 쓰는게
Form Widget
- 웹 페이지에서 Form Input 요소가 어떻게 렌더링 되어서 보여질지 정의한다.
- Form Fields에 할당해서 사용한다.
articles/forms.py (text field)
from django import forms class CommentForm(forms.Form): name = forms.CharField() url = forms.URLField() comment = forms.CharField(widget=forms.Textarea)
from django import forms class ArticleForm(forms.Form): # 앞은 데이터베이스에 저장될 값, 뒤는 사용자에게 보여질 값 GENRE_CHOICES = [ ("technology", "Technology"), ("life", "Life"), ("hobby", "Hobby"), ] title = forms.CharField(max_length=10) content = forms.CharField(widget=forms.Textarea) genre = forms.ChoiceField(choices=GENRE_CHOICES)
Django Model Form Class
알아서 Model을 참조해 Form을 만들어주는 ModelForm Class
폼 클래스와 마찬가지로 articles/forms.py에서 만들어주면 된다.
폼 클래스에서는 (forms.Form)을 상속받았다면, 얘는 (forms.ModelForm)을 상속받는다.
from django import forms from articles.models import Article class ArticleForm(forms.ModelForm): class Meta: model = Article fields = "__all__" # exclude = ["title"] 제외하고자 하는 옵션
어떤 Model을 참조해야 되는지 알려주는 코드 : Meta class
class Meta:
이 model에 있는 모든 field에 대해서 입력을 받겠다는 의미 : "__all__"
fields = "__all__"
서버 실행 해보면
에러 없이 한번에 되니 세상을 가진 것 같다...ㅎㅎ
view에서 Django Model Form 사용하기
게시글이 작성됐다면, 폼에는 반드시 데이터가 채워져서 저장되었을거다.
기존에 작성했던 코드↓
def create(request): title = request.POST.get("title") content = request.POST.get("content") article = Article.objects.create(title=title, content=content) return redirect("article_detail", article.pk)
즉, Form에 데이터가 채워져있는 상태로 요청을 받도록 코드를 수정해보자.
→ 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") ...
★ 이렇게 수정해주면, 서버 실행해서 확인해봐도 데이터가 채워져야만 저장이 되는 걸 확인할 수 있다.
🤔 조금 더 생각해보자
현재 new 함수와 create 함수가 많이 흡사하니까
def new(request): form = ArticleForm() context = { "form": form, } return render(request, "new.html", context)
⇒ 그냥 create 함수 하나로 처리해보자.
- request가 GET 방식으로 들어오면 비어있는 Form 렌더링해서 주고, POST 방식으로 들어오면 데이터 채워서 보낸거니까 새로운 article을 생성하면 된다.
new - create 수정하기
- articles/views.py 로 들어와서 create 코드 수정
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 함수는 필요 없어졌으니까 지워주고, urls.py 들어가서 path도 지워준다.
- new.html을 create.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 %}
- articles.html
{% extends 'base.html' %} {% block content %} <h1>Articles</h1> <a href="{% url 'create' %}">새 글 작성하기</a> # 'new'를 'create'로 변경 {% for article in articles %} <a href="{% url 'article_detail' article.pk %}"> <p>[ {{ article.pk }} ] {{ article.title }}</p> </a> {% endfor %} {% endblock content %}
edit - update
edit과 update 얘네도 하나로 합쳐주자.
로직을 살펴보자 🤔
update
- 일단, get으로 들어오든 post로 들어오든 조회해야 한다.
- 만약, request.method가 POST방식이면, POST로 넘어온 데이터로 새로운 Article을 만들건데, 원래의 article에 업데이트 해야해.
- 만약에, 이 폼에 채워진 데이터가 유효하다면 저장해. article = form.save
- 저장한 후에는 article_detail(게시글 상세페이지)로 리다이렉트
edit
- edit은 게시글을 수정해주는 것이기 때문에, 폼이 비어있으면 안 된다. 채워져있는 폼을 수정해주는 거다.
- 이전에 작성했던 데이터는 article 개체에 들어있다. article 개체를 form에 넣는게 instance=article이므로
form = ArticleForm(instance=article)
- ↑ 이렇게 하면 이 article에 들어있는 title과 content를 빼서 form에 채운 상태로 작성된다.
- 이렇게 데이터를 채워서 모델 폼을 만들어 놓고나서, 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(): 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)
마찬가지로 이제 edit 필요없음
뷰에서 edit 함수 지우고, urls에서도 지워주고, 코드 확인해서 그 외 edit 이 쓰이고 있으면 다 지워주면 됨.
edit.html 도 update.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 %}
잘 된다. ㅎㅎ 이제 서버 실행했을 때 에러나면 수정 바로잡는 법도 조금 익숙해진 것 같다😊
'Django' 카테고리의 다른 글
Django 회원기능 구현하기 (0) 2024.08.18 Django Auth, Login & Logout (4) 2024.08.17 Django Model, Migration, ORM, Database API (0) 2024.08.16 Django HTTP Form (0) 2024.08.14 Django Template System (DTL 문법, 템플릿 상속) (0) 2024.08.13