티스토리 뷰
Django에서 Form을 언제 쓸까?
- 사용자가 정보를 적을 수 있게 from양식을 사용자에 준다.
- 그 후에 Form을 통해 사용자가 보낸 정보를 사용한다.
일단 예시를 보고 흐름을 간단히 이해를 해보자.
<form action="/boards/complete/">
제목 : <input type="text" name="title">
<br>
내용 : <input type="text" name="content">
<input type="submit" value="작성">
</form>
form내부의 action에서 /의 중요성
지금부터 하드typing을 했을 때 POST에서 발생 할 수 있는 오류를 알아보자.
뒤의 / 제외 시
ex) action="/article/create" method="POST"
Error내용은 GET을 할 떄만 redirect 되다 보니, POST를 내부적으로 /를 닫는 형식으로 처리하고 싶었지만, POST 요청으로는 불가능하다고 뜬다. GET 요철일 떄는 error 안뜬다. 쉽게 말하면 redirect 할 때, POST 데이터를 들고 다른 곳으로 보낼 수 없다
즉, 포인트는 장고는 url을 적을 때 맨 뒤 /도 닫아준다.(다른 프로그램은 안 그런 경우가 많다.)
앞 /를 제외 시
상대 경로로, 도메인 기준이 아니라 뒤에 추가가 된다.
Form 설명
action - 어디로 보내면 되는지 적는 곳이다. 요청을 처리할 url을 적는다.
input 안의 name - 어떤 변수에 담아서 보내는지를 나타낸다. 사용자가 입력한 것을 담는 변수의 이름이다. 즉, 각각의 내용을 담아서 보내기 위해서는 name이 필요하다.
보내지는 과정
action을 통해 어떻게 url이 보내질까??
만약 서버를 실행 후에 제목의 input에 hanpy를 적고 내용의 input에 파이썬을 적고, 작성을 눌렀다고 해보자.
그때의 url은
www.(기본주소).com/borads/complete/?title=hanpy&content=파이썬
이런식으로 생성되서 보내진다.
즉, form 태그의 action과 name을 통해 새로운 url이 만들어진다.
보낸 후의 과정
form의 action을 통해 데이터를 보내면,
urls.py의 path('boards/complete/', views.complete), 에서 받고, views의 complete함수로 다시 간다.
그리고 complete함수를 실행한 후에 return 되는 곳으로 이동 하게 된다.
이 때 정보가 어떻게 넘어오는지 아래의 코드로 확인을 해보자.
def complete(request):
print(request.GET)
print(request.method)
print(request.path)
return render(request, 'boards/complete.html')
request
request는 요청과 관련된 객체이면서 요청되는 모든 정보를 가지고 있다라는 점을 인지하고, 아래의 출력값들을 이해하자.
print(request.GET)
(출력값) <QueryDict: {'title': ['hanpy'], 'content':['파이썬']}> (이렇게 딕셔너리로 넘어간다)
print(request.method)
> GET
print(request.path)
> /boards/complete/
그렇다면, 받은 정보를 어떻게 html로 보낼 수 있을까?
context에 담아서 HTML로 보내기가 가능하다.
물론 context에 안 담고 아래에 있는 코드의 render의 세번째 인자에 딕셔너리로 바로 보내도 되긴한다. 그러나 매우 길어지는 문제점이 있다.
def complete(request):
title = request.GET.get('title')
content = request.GET.get('content')
context = {
'title': title
'content' : content
}
return render(request, 'boards/complete.html', context)
GET.get은 값을 불러오기 위해 정해진 것이라는 정도로 일단 이해하고 암기하자.
위에서 굵은 글씨 표시가 된, title과 content는 request.GET의 QuerySet에서 딕셔너리의 key값으로 값을 가져와서 저장한다.
+render는 html을 만들기 위해 templates가 작업을 한다.
complete.html에서
<h2>{{ title }}</h2> 이라고 적으면 'hanpy'가 뜨고
<p>>{{ content }}</p> 이런식으로 적으면 p태그에 파이썬이라는 '문자열'이 들어가서 나온다.
ModelForm
Form에서 ModelForm으로 바뀌면서 Create로직이 바뀌는 과정을 이해해야한다.
Form
Form을 만들기 위해서는 보통 목록을 만들고 새글 쓰기를 하면서 아래와 같이 진행한다.
app 내부의 파일들을 건든다.
forms.py
from django import forms
class ArticleForm(forms.Form):
titile = forms.CharField()
content = forms.CharField(widget=forms.Textarea)
+ form에서는 CharField에 max_length가 필수가 아니다. 그리고 widget는 생김새를 결정 하는 거다
views.py
from .forms import ArticleForm
def create(request):
form = ArticleForm()
context = {
'form' : form
}
return render(request, 'articles/create.html', context)
create.html
<form action = "">
{{ form }}
</form>
+{{ form }} 을 {{ form.as_p }} 로 바꾸면 인라인이 p 태그로 변한다.(한줄에 있는데 title과 content로 2줄로 바뀐다.)
form로직을 만들었다. 그런데 개발자들이 곰곰히 생각하니 forms.py와 models.py가 비슷하다. 그러면 forms.py에서 정의한 ArticleForm이 models.py에서 정의 한 Article의 설정을 그대로 가져올 수 없을까? 라는 생각으로 ModelForm이 탄생했다.
ModelForm
ModelForm은 모델에서 정의한 것을 그대로 양식으로 반환을 해준다.
검증도 해주면서, 실패하면 error도 반환해 준다.
코드(forms.py)
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm)
class Meta:
model = Article :Article과 관련있다고 적은거다
fields = ['title', 'content'] : Article 클래스에서 적은 내용만 가져오겠다는 내용이다.
여기서 처음으로 메타데이터에 관련된 내용이 나온다. 메타데이터란 데이터의 데이터란 의미다.
MetaData (메타클래스)
데이터의 데이터라는 의미로 예를 들면 사진이라는 데이터가 있으면 메타데이터는 노출량이라던가 찍은 시간 같은 것을 나타낸다. 즉, 필드정보에 대한 Data를 메타클래스에 담아 놓는다.
1. 필드는 어떠한 모델과 연결하는가? model
2. 어떤 필드를 정의할 것인가? field
추가적인 부분은 Meta 부분의 게시물을 참고하자.
ModelForm의 장점
1. 모델을 정의하면 자동으로 form을 만들어 준다
2. form이 추가적으로 가져야 할 기능이 있다. 그것을 ModelForm이 해결해 준다.
2-1. 양식을 점검해 준다.(미작성이 있으면 작성하라고 말해준다.)
request.GET or request.POST를 통해 바로 저장하는것이 아니라 form.is_valid()를 이용해서 미작성을 잡아낸다.
이러한 형식으로 아래의 create.html이 완성된다. 그리고 CRUD 기초부분에서 적었던 views.py부분의 new와 create가 분기로 합쳐진다.
{% extends 'base.html' %}
{% block body %}
<h2>새 글쓰기</h2>
<form action="" method='POST'>
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="제출">
</form>
{% endblock %}
Q
from django import forms
class ArticleForm(forms.Modelform)
여기서 굳이 forms내부를 다 불러 올필요 없이 forms안에 있는 Modelform만 불러오면 안되나요?
물론 form django.forms import Modelform 으로 불러 와도 됩니다.이런경우에는
class ArticleForm(Modelform)
class Meta;
이런식으로 적어주면된다. 이렇게 적을 경우 단점은 CharField와 TextField를 적으려면 추가를 해야한다.
form django.forms import Modelform, CharField, TextField로 적어야하고 다른 것들도 적을 때 마다 추가를 시켜야 한다.
views.py
def create(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
article = form.save()
return redirect('articles:index')
else:
form = ArticleForm()
context = {
'form' : form
}
return render(request, 'articles/new.html',context)
Form 꾸미기(3가지 방법)
1.평범하게 form 꾸미기
form.html
{{ form.as_p }}
2. loop 활용 (쪼개기)하여 form꾸미기
공식문서) django form customise 검색
https://docs.djangoproject.com/en/3.0/topics/forms/
들어가서 Looping over the form’s fields부분을 보자
쉽게 말해 각각의 field를 반복문으로 출력가능하다. {{ form }}으로 통으로 묶여 있는걸 분리하여 조작 가능하게 하는것이다. 들어가서 코드확인을 해보자.
HTML의 {{ form.as_p }} 대신
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
을 붙여 넣어주면 되는구만.
CSS 넣을려면 HTML이 아니고 forms.py를 작업해 준다. 위젯을 만들어서 모델 폼 클래스 안에 채워 넣는다.
forms.py
from .models import Article
class ArticleForm(forms.ModelForm):
title = forms.CharField(
max_length=100,
label='제목',
help_text='제목은 100자이내로 작성하세요.',
widget=forms.TextInput(
attrs={
'class': 'my-input',
'placeholder': '제목 입력'
}
)
)
content = forms.CharField(
label='내용',
help_text='자유롭게 작성해주세요.',
widget=forms.Textarea(
attrs={
'row': 5,
'col': 50,
}
)
)
class Meta:
model = Article
fields = ['title', 'content']
widget은 Textinput과 Textarea가 있다.
field는 불편하더라도 다 적어줘야 한다.
3. bootstrap 활용해서 form 꾸미기
기본적으로 앞에서 배운 것 처럼
Bootstrap 구글 검색 후 사이트 접속 - Component클릭 - forms 클릭
https://getbootstrap.com/docs/4.5/components/forms/
들어가보면 굉장히 다양한 종류가 있다. 쓰고 싶은거 써도 된다.
위에서 써도 되지만 우리는 서드파트라이브러리를 써본다.
구글에 django bootstrap4를 검색해 보자.
장고에 적용 잘되는 라이프러리(패키지)를 쓰는거다.
https://django-bootstrap4.readthedocs.io/en/latest/
설치) pip install django-bootstrap4
터미널에 치고 installedapp에 등록하자. => 'bootstrap4',
Quickstart 보니
base.html에 추가하자
<!DOC~ 바로 밑에
{% load bootstrap4 %}
</head> 바로위에
{% bootstrap_css %}
</body> 바로위에
{% bootstrap_javascript jquery='full' %}
을 추가한다.
아래와 같이 코드 적으면 된다.
<!DOCTYPE html>
{% load bootstrap4 %}
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Django Live Session</title>
{% bootstrap_css %}
</head>
<body>
<div class="container">
{% block body %}
{% endblock %}
</div>
{% bootstrap_javascript jquery='full' %}
</body>
</html>
각각의 html에 각 파일 마다 import 하는것 처럼 {% load bootstrap4 %}도 모든 html에 넣는다
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block body %}
위와 같은 위치에 넣어 주면 된다.
bootstrap form 최종
그리고 form은 아래와 같이 적어준다.(편하기 때문에 이거 주로 사용할 거다.)
<form action="" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<button class="btn btn-primary">제출</button>
</form>
+ 지금까지는 input type='submit'을 사용 했지만, button을 만들면 타입 지정없이 동작이 가능하다.
'Web > Django' 카테고리의 다른 글
[Django] Migration (0) | 2020.06.26 |
---|---|
[Django] ORM (0) | 2020.06.24 |
[Django] CRUD_READ_상세보기(detail) (0) | 2020.06.21 |
[Django]html의 탐색 순서에 따른 오류 해결책 (0) | 2020.06.20 |
[Django]코딩을 위한 잡다한 추가 팁 (0) | 2020.06.18 |
- Total
- Today
- Yesterday
- vuejs
- logout
- react autoFocus
- login
- JavaScript
- 클라우데라
- error:0308010C:digital envelope routines::unsupported
- typescript
- UserCreationForm
- Express
- useHistory 안됨
- Python
- mongoDB
- Deque
- nodejs
- TensorFlow
- 자료구조
- Queue
- read_csv
- django
- pandas
- Vue
- nextjs autoFocus
- 자연어처리
- useState
- next.config.js
- react
- BFS
- DFS
- NextJS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |