# articles/models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
# articles/forms.py
from django import forms
class ArticleForm(forms.Form):
title = forms.CharField(max_length=50)
content = forms.CharField(widget=forms.Textarea)
# articles/views.py
from.forms import ArticleForm
⁝
def new(request):
form = ArticleForm()
context = {
"form": form,
}
return render(request, "new.html", context)
⁝
<!-- articles/templates/new.html -->
<h1>New Articles</h1>
<form action="{% url 'create' %}" method="POST">
{% csrf_token %}
{{ form.as_p }} <!-- form 적용 -->
<button type="submit">저장</button>
</form>
Form rendering options
- label과 input을 렌더링하는 것에 대한 옵션
- as_div: <div>
태그로 감싸져서 렌더링
- as_p: <p>
태그로 감싸져서 렌더링
- 공식 문서: Form Rendering Options
Form Widget
- 웹 페이지에서 Form Input 요소가 어떻게 렌더링 되어서 보여질지 정의
- Form Fields에 할당해서 사용
- 공식 문서: Form Widget
# articles/forms.py
from django import forms
from articles.models import Article
class ArticleForm(forms.ModelForm):
# '어떤 모델을 가져와서 Form을 만들어야 하는가?'를 Meta class에 정의
class Meta:
model = Article # 가져올 model
fields = "__all__" # model에서 가져올 속성들
# exclude = ["created_at", "updated_at"] # fields 중에서 제외할 것들
# 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")
⁝
views.py
의 new
함수와 create
가 상당히 유사하게 생김new
함수: request.method == GET 이면 새로운 빈 Form을 만들어 보여줌create
함수: request.method == POST이면 값이 채워진 Form을 새롭게 만들어 저장new
함수를 create
에 병합views.py
에서 new
함수 지우기urls.py
에서 new
로 가는 path 지우기new.html
의 이름을 create.html
로 바꾸기# new함수를 create함수에 병합
def create(request):
# 기존 create 함수 부분
if request.method == "POST":
form = ArticleForm(request.POST) # 데이터가 바인딩된(값이 채워진) Form
if form.is_valid(): # Form이 유효하다면 데이터를 저장하고 다른 곳으로 redirect
article = form.save()
return redirect("article_detail", article.pk)
# 기존 new 함수 부분
else:
form = ArticleForm()
context = {"form": form}
return render(request, "create.html", context)
<!-- articles.html에서도 new url을 create url로 변경 -->
<h1>Articles</h1>
<a href="{% url 'create' %}"><button>Create New Article</button></a>
{% for article in articles %}
<!-- article_detail에 필요한 인자인 article.pk를 같이 넘겨줌 -->
<a href="{% url 'article_detail' article.pk %}">
<p>[ {{ article.pk }} ] {{ article.title }}</p>
</a>
<br/>
{% endfor %}
<!-- new.html을 create.html로 변경 -->
<h1>New Articles</h1>
<form action="{% url 'create' %}" method="POST">
{% csrf_token %}
{{ form.as_p }} <!-- form을 p 태그로 감싸겠다는 의미 -->
<button type="submit">저장</button>
</form>
<br/>
<a href="{% url 'articles' %}">목록 보기</a>
views.py
의 edit
함수와 update
가 상당히 유사하게 생김edit
함수: GET 이면 article값으로 채워진 Form을 만들어 내용 수정update
함수: POST이면 article값으로 채워진 Form을 만들어 수정된 내용 저장edit
함수를 update
에 병합views.py
에서 edit
함수 지우기urls.py
에서 edit
로 가는 path 지우기edit.html
의 이름을 update.html
로 바꾸기# edit함수를 update함수에 병합
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) # article의 값을 가지는 객체로 채워진 Form
context = {
"form": form,
"article": article,
}
return render(request, "update.html", context)
<!-- article_detail.html에서도 edit url을 update url로 변경 -->
<h1>Article Detail</h1>
⁝
<a href="{% url 'articles' %}">목록보기</a><br/>
<a href="{% url 'update' article.pk %}"><button>수정</button></a>
<!-- edit.html을 update.html로 변경 -->
<h1>Update Article</h1>
<form action="{% url 'update' article.pk %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">수정</button>
</form>
<br/>
<a href="{% url 'article_detail' article.pk %}">이전으로</a>