form이라는 클래스를 통해 많은양의 칼럼이 있을 때 쉽게 할수 있음
프로젝트 04에서의 불편함? 을 해소
Create / list
기본설정
1
2
3
4
5
6
7
8
9
10
11
# movie urls.py
from django.urls import path
from . import views
app_name = "moviews"
## name 을 써주기 위해 app_name설정
urlpatterns = [
path("", views.list, name="list"),
path("create/", views.create, name="create"),
]
1
2
3
4
5
6
7
8
9
# movie views.py
from django.shortcuts import render
def list(request):
pass
def create(request):
pass
모델
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# movie models.py
from django.db import models
class Movie(models.Model):
title = models.CharField(max_length=100)
title_en = models.CharField(max_length=100)
audience = models.IntegerField()
open_date = models.DateField()
genre = models.CharField(max_length=100)
watch_grade = models.CharField(max_length=100)
score = models.FloatField()
poster_url = models.TextField()
description = models.TextField()
def __str__(self):
return self.title
1
2
$ python manage.py makemigrations
$ python manage.py migrate
create
1
2
3
4
# movie views.py
def list(request):
movies = Movie.objects.all()
return render(request, "movie/list.html", {"movies":movies})
1
2
3
4
5
6
7
8
9
# base.html // list.html 만들기
{% extends "movie/base.html" %}
{% block body %}
{% for movie in movies %}
<h1>list page</h1>
{% endfor %}
{% endblock %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# movie views.py
def create(request):
if(request.method == "POST"):
title = request.POST.get("title")
title_en = request.POST.get("title_en")
audience = request.POST.get("audience")
open_date = request.POST.get("open_date")
genre = request.POST.get("genre")
watch_grade = request.POST.get("watch_grade")
score = request.POST.get("score")
poster_url = request.POST.get("poster_url")
description = request.POST.get("description")
Movie.objects.create(
title=title, title_en=title_en, audience=audience, open_date=open_date,
genre=genre, watch_grade=watch_grade, score=score, poster_url=poster_url, description=description
)
return redirect("movies:list")
else:
return render(request, "movie/create.html")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# create.html
{% extends "movie/base.html" %}
{% block body %}
<form method="POST">
{% csrf_token %}
제목 : <input type="text" name="title" required /> <br>
영문제목 : <input type="text" name="title_en" required /> <br>
관객수 : <input type="number" name="audience"/> <br>
개봉일 : <input type="date" name="open_date"/> <br>
장 르 : <input type="text" name="genre"/> <br>
관람등급 : <input type="text" name="watch_grade"/> <br>
점 수 : <input type="number" step="0.01" name="score"/> <br>
포스터 : <input type="text" name="poster_url"/> <br>
상세설명 : <textarea name="description"></textarea> <br>
<input type="submit" value="Submit"/>
</form>
{% endblock %}
불편한점
- column이 많아서 작성 시간이 오래걸림
- 입력이 비어도 입력이 됨 (required를 붙여주면 해결) - 하지만 완벽한 해결이 아님.
- 유효성 검사가 필요
Form을 활용한 create (유효성 검사)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# movie forms.py 생성
from django import forms
from django import forms
class MovieForm(forms.Form):
title = forms.CharField(max_length=100)
title_en = forms.CharField(max_length=100)
audience = forms.IntegerField()
open_date = forms.DateField(
widget=forms.widgets.DateInput(attrs={"type":"date"})
)
genre = forms.CharField(max_length=100)
watch_grade = forms.CharField(max_length=100)
score = forms.FloatField()
poster_url = forms.CharField(max_length=100)
description = forms.CharField(widget=forms.Textarea())
# forms생성시 자동으로 label과 required가 자동으로
- django는 dateField를 지원하지 않음 - 브라우저별로 지원하거나 안하는게 있음
- 그래서 추가해줘야 함 ( open_date와 description )
1
2
# movie urls.py
path("form_create/", views.form_create, name="form_create"),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# movie views.py
from django import forms
def form_create(request):
if(request.method == "POST"):
form = MovieForm(request.POST)
# MovieForm을 인스턴스화
## 할당된 form 은 유효성 검사에 사용
if(form.is_valid()):
title = form.cleaned_data.get("title")
title_en = form.cleaned_data.get("title_en")
audience = form.cleaned_data.get("audience")
open_date = form.cleaned_data.get("open_date")
genre = form.cleaned_data.get("genre")
watch_grade = form.cleaned_data.get("watch_grade")
score = form.cleaned_data.get("score")
poster_url = form.cleaned_data.get("poster_url")
description = form.cleaned_data.get("description")
Movie.objects.create(
title=title, title_en=title_en, audience=audience, open_date=open_date,
genre=genre, watch_grade=watch_grade, score=score, poster_url=poster_url, description=description
)
return redirect("movies:list")
else:
form = MovieForm()
return render(request, "movie/form_create.html", {"form":form})
# forms생성시 자동으로 label과 required가 자동으로
1
2
3
4
5
6
7
8
9
10
11
12
# form_create.html 생성
{% extends "movie/base.html" %}
{% block body %}
<form method="post">
{% csrf_token %}
<input type="submit" value="Submit"/>
</form>
{% endblock %}
- as_p // as_table // as_ul 이 있음
1
2
3
<table>
</table>
django-bootstrap4
1
$ pip install django-bootstrap4
1
2
3
# setting.py
INSTALLED_APPS에 'bootstrap4', 추가
1
2
3
4
5
# base.html
맨위에
{% load bootstrap4 %}
head맨 밑에
{% bootstrap_css %}
1
2
3
4
5
6
7
8
9
10
11
12
13
# form_create.html 수정
{% extends "movie/base.html" %}
{% load bootstrap4 %}
{% block body %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Submit"/>
</form>
{% endblock %}
detail(read)
1
2
# movie urls.py
path("<int:id>/", views.detail, name="detail"),
1
2
3
4
# movie views.py
def detail(request, id):
movie = Movie.objects.get(id=id)
return render(request, "movie/detail.html", {"movie":movie})
update
1
2
# movie urls.py
path("<int:id>/form_update/", views.form_update, name="form_update"),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# movie views.py
def form_update(request, id):
movie = Movie.objects.get(id=id)
if(request.method == "POST"):
form = MovieForm(request.POST)
if(form.is_valid()):
title = form.cleaned_data.get("title")
title_en = form.cleaned_data.get("title_en")
audience = form.cleaned_data.get("audience")
open_date = form.cleaned_data.get("open_date")
genre = form.cleaned_data.get("genre")
watch_grade = form.cleaned_data.get("watch_grade")
score = form.cleaned_data.get("score")
poster_url = form.cleaned_data.get("poster_url")
description = form.cleaned_data.get("description")
movie.title = title
movie.title_en = title_en
movie.audience = audience
movie.open_date = open_date
movie.genre = genre
movie.watch_grade = watch_grade
movie.score = score
movie.poster_url = poster_url
movie.description = description
movie.save()
return redirect("movies:detail", id)
else:
data = {
"title":movie.title,
"title_en":movie.title_en,
"audience":movie.audience,
"open_date":movie.open_date,
"genre":movie.genre,
"watch_grade":movie.watch_grade,
"score":movie.score,
"poster_url":movie.poster_url,
"description":movie.description
}
form = MovieForm(data)
return render(request, "movie/form_update.html", {"form":form})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# form_update.html
## form_create.html과 코드가 동일
### 즉 form은 한개만 만들어도 됨
{% extends "movie/base.html" %}
{% load bootstrap4 %}
{% block body %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Submit"/>
</form>
{% endblock %}
단순화
create
1
2
# movie urls.py
path("<int:id>/form_update/", views.form_update, name="form_update"),
1
2
3
4
5
6
7
8
9
10
11
12
# movie views.py
from .forms import MovieModelForm
def model_form_create(request):
if(request.method == "POST"):
form = MovieModelForm(request.POST)
if(form.is_valid()):
form.save()
return redirect("movies:list")
else:
form = MovieModelForm()
return render(request, "movie/model_form_create.html",{"form":form})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# movie forms.py에 새로운 class 추가
from .models ipmort Movie
class MovieModelForm(forms.ModelForm):
# Meta클래스 오버라이딩
class Meta:
# 기본적으로 두가지 항목을 넣게 되어 있음
## 모델을 알려주면 자동으로 어울리는 걸 매칭해줌
model = Movie
# 전체 필드를 가져오기
fields = '__all__'
## open_date를
widgets = {
"open_date":forms.DateInput(attrs={'type':'date'})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# model_form_create.html 생성
## 코드는 form코드와 동일
{% extends "movie/base.html" %}
{% load bootstrap4 %}
{% block body %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Submit"/>
</form>
{% endblock %}
update
1
2
3
# movie urls.py
path("<int:id>/model_form_update/", views.model_form_update, name="model_form_update"),
1
2
3
4
5
6
7
8
9
10
11
# movie views.py
def model_form_update(request, id):
movie = Movie.objects.get(id=id)
if(request.method == "POST"):
form = MovieModelForm(request.POST, instance=movie)
if(form.is_valid()):
form.save()
return redirect("movies:detail", id)
else:
form = MovieModelForm(instance=movie)
return render(request, "movie/model_form_update.html", {"form":form})