#forms.py
from django import forms
class ArticleForm(forms.Form) :
# Models.py와 유사한 구조 (form 클래스를 상속받음)
title = forms.CharField(max_length=10)
#글자는 10글자로 고정
content = forms.CharField()
#new.html
<h1>NEW</h1>
<hr>
<form action="{% url 'articles:create' %}" method="POST">
{% csrf_token %}
{{form}}
<input type="submit">
</form>
<a href="{% url 'articles:index' %}">back</a>
#views.py new함수
def new(request):
form = ArticleForm()
context = {
'form' : form,
}
return render(request, 'articles/new.html',context)
as_p()
태그로 감싸져서 렌더링 됨 )
as_ul()
as_table()
from django import forms
class ArticleForm(forms.Form) :
# Models.py와 유사한 구조 (form 클래스를 상속받음)
title = forms.CharField(max_length=10)
#Textarea 위젯 사용 !
content = forms.CharField(widget=forms.Textarea)
from django import forms
class ArticleForm(forms.Form) :
REGION_A = 'sl'
REGION_B = 'dj'
REGION_C = 'bs'
REGIONS_CHOICES = [
(REGION_A, '서울'),
(REGION_B, '대전'),
(REGION_C, '광주')
]
# Models.py와 유사한 구조 (form 클래스를 상속받음)
title = forms.CharField(max_length=10)
content = forms.CharField(widget=forms.Textarea)
# select 태그 만들기
region = forms.ChoiceField(choices = REGIONS_CHOICES, widget = forms.Select())
#기존의 Form을 ModelForm으로 변경
class ArticleForm(forms.ModelForm) :
class Meta :
model = Article
fields = '__all__'
#exclude = ('title',)
def create(request):
form = ArticleForm(request.POST)
#form에서 전달한 데이터가 유효하면 저장하고 detail을 redircet해라
if form.is_valid() :
# form.save()를 하면 생성된 객체를 리턴한다.
article = form.save()
return redirect('articles:detail',article.pk)
#유효하지 않으면 에러를 출력하고 new로 돌아감
print(form.errors)
return redirect('articles:new')
# title = request.POST.get('title')
# content = request.POST.get('content')
# article = Article(title=title, content=content)
# article.save()
# return redirect('articles:detail', article.pk)
유효성 검사를 실행하고, 데이터가 유효한지 여부를 Boolean으로 반환
데이터 유효성 검사를 보장하기 위한 많은 테스트에 대해 Django는 is_valid()를 제공
유효성 검사
def create(request):
if request.method == 'POST' :
form = ArticleForm(request.POST)
#form에서 전달한 데이터가 유효하면 저장하고 detail을 redircet해라
if form.is_valid() :
# form.save()를 하면 생성된 객체를 리턴한다.
article = form.save()
return redirect('articles:detail',article.pk)
#유효하지 않으면 다시 new로 가라
# title = request.POST.get('title')
# content = request.POST.get('content')
# article = Article(title=title, content=content)
# article.save()
# return redirect('articles:detail', article.pk)
elif request.method == 'GET' :
form = ArticleForm()
context = {
'form' : form,
}
# 유효성 검사를 통과하지 못하면 form은 에러메시지를 담고 있다. 그래서 에러메시지를 출력한다.
return render(request, 'articles/create.html',context)
def update(request, pk):
article = Article.objects.get(pk=pk)
if request.method == 'POST' :
# instacne=article을 안써주면 새로운 글을 만든다.
form = ArticleForm(request.POST,instance=article)
if form.is_valid() :
article=form.save()
return redirect('articles:detail', article.pk)
elif request.method == 'GET' :
# 기존 정보를 받아서 update.html을 표시하기
form = ArticleForm(instance=article)
context = {
'article' : article,
'form': form
}
return render(request, 'articles/update.html', context)
POST를 if문 첫번째로 사용하는 이유는 POST는 DB와 관련이 있기 때문에 POST로 들어올 때만 DB에 접근하도록 하기 위해서이다
메타 클래스 내부
권장하지 않음
메타 클래스 상위를 권장
class ArticleForm(forms.ModelForm) :
# 장고 모델을 참고해서 form을 만들어줌
# input에 속성을 넣으려면 widget 내부 attribute에 작성을 해야한다.
title = forms.CharField(
widget=forms.TextInput(
# attributes
attrs = {
'class' : 'my-title',
'placeholder':'Enter the title',
}
)
)
class Meta :
model = Article
# 전체 필드 출력하는 __all__
fields = '__all__'
#exclude = ('title',)
class ArticleForm(forms.ModelForm) :
# 장고 모델을 참고해서 form을 만들어줌
# input에 속성을 넣으려면 widget 내부 attribute에 작성을 해야한다.
title = forms.CharField(
widget=forms.TextInput(
# attributes
attrs = {
'class' : 'my-title',
'placeholder':'Enter the title',
}
)
)
content = forms.CharField(
widget = forms.Textarea(
attrs={
'class' : 'my-content',
'placeholder' :'Enter the content',
}
),
error_messages={
'required' : 'Please enter your content!!!!!',
}
)
ResolverMatch(func=articles.views.create, args=(), kwargs={}, url_name=create, app_names=['articles'], namespaces=['articles'], route=articles/create/)
이렇게 매칭된 결과를 볼 수 있다.
Create와 update는 이전 데이터가 있으면서 그 인스턴스를 수정하는 것인지 새로 생성한는 것인지의 차이로 html이 거의 동일하게 구성되어 있다.
따라서, form.html에 해당 html 두가지를 모두 구성할 수 있게 변경한다.
request.resolver_math.url_name을 통해 구분하도록 한다.
{% block content %}
{% comment %} url이 create이면 {% endcomment %}
{% if request.resolver_match.url_name == 'create' %}
<h1>CREATE</h1>
{% else %}
{% comment %} edit이면 {% endcomment %}
<h1>EDIT</h1>
{% endif %}
<hr>
<form action="" method="POST">
{% csrf_token %}
{% bootstrap_form form %}
{% comment %} {{form.as_p}} {% endcomment %}
<input type="submit">
</form>
{% if request.resolver_match.url_name == 'create' %}
{% comment %} url이 crate면 메인으로 가는 back 만들기 {% endcomment %}
<a href="{% url 'articles:index' %}">back</a>
{% else %}
<a href="{% url 'articles:index' %}">Home</a>
<a href="{% url 'articles:detail' article.pk %}">back</a>
{% endif %}
{% endblock content %}
<h2>1. Rendering fields manually</h2>
<form action="{% url 'articles:create' %} " method="POST">
{% csrf_token %}
<div>
{{form.title.errors}}
{{form.title.label_tag}}
{{form.title}}
</div>
<div>
{{form.content.errors}}
{{form.content.label_tag}}
{{form.content}}
</div>
<input type="submit">
</form>
<h2>2. Looping over the form's fields</h2>
<form action="{% url 'articles:create' %}" method="POST">
{% csrf_token %}
{% for field in form%}
{% if field.errors %}
{% for error in field.errors %}
<div class="alert alert-danger">{{error}}</div>
{% endfor %}
{% endif %}
{{field.errors}}
{{field.label_tag}}
{{field}}
{% endfor %}
<input type="submit">
</form>