Form은 HTML에서 적어도 한 개 이상의 type="submit"인 input 요소를 포함하는 <form>...</form> 태그 사이의 요소들의 집합으로 정의된다.
Form의 속성은 아래 두 가지로 구성된다.
<form action="/team_name_url/" method="post">
<label for="team_name">Enter name: </label>
<input id="team_name" type="text" name="name_field" value="Default name for team.">
<input type="submit" value="OK">
</form>
Django는 HTTP Request에 대해 아래와 같이 동적한다.
1. 뷰가 요청을 받고, 모델로 부터 데이터를 읽는 것을 포함한 요구된 동작을 수행한다.
2. 보여줄 데이터를 포함한 Context를 전달받은 템플릿으로부터 HTML Page를 생성하고 반환한다.
이 때, Django는 서버/사용자가 입력한 데이터를 처리 가능해야하며, 에러가 있으면 그 페이지를 다시 보여줄 필요가 있다.
아래 Diagram은 Django가 요청을 처리하는 플로우 차트다.
위 플로우 차트에서, Django Form이 주요하게 다루는 사항은 아래와 같다.
- 사용자가 처음으로 폼을 요청할 때 기본 폼을 보여준다.
- 폼은 비어있거나 초기값으로 채워져있으며, 이렇게 유저가 입력한 값과 무관한 값을 unbound 상태라고 한다.
- 제출 요청으로 부터 데이타를 수집하고 그것을 폼에 결합한다.
- 입력 데이터가 유효성을 위반한 경우, 에러메시지가 폼을 재표시
- 데이타를 다듬어서 유효성을 검증한다.
- 사용자 입력을 정화(sanitisation) 하고 (공격성 문자를 제거 등) python에서 사용하는 타입의 데이타로 변환
- 입력된 어떤 데이타가 유효하지 않다면, 폼을 다시 표시한다.
- 이 때, 표시값은 초기값이 아닌 유저 입력값과 에러 메시지
- 입력된 모든 데이타가 유효하다면, 요청된 동작을 수행한다.
- 일단 모든 작업이 완료되었다면, 사용자를 새로운 페이지로 보낸다.
1. Django는 login url을 urls.py에 따라 views.py의 login 함수 호출
2. login 함수는 forms.py의 LoginForm 인스턴스 생성
3. LoinForm 인스턴스는 forms.Form을 상속받은 클래스로, 필요한 폼 요소들이 forms의 값(?)을 상속받아 재정의한 변수형태로 선언되어있다.
4. views.py의 login 함수는 login.html 템플릿을 불러오고, LoginForm 인스턴스의 값을 사용하여 렌더링해 반환한다.
class LoginForm(forms.Form):
username = forms.CharField(
error_messages={
'required': '아이디를 입력해주세요.'
},
label="사용자 이름",
max_length=32
)
password = forms.CharField(
widget=forms.PasswordInput,
label="비밀번호",
error_messages={
'required': '비밀번호를 입력해주세요.'
}
)
# 기본적으로는 is_valid 를 통해 값이 들어있는지 아닌지가 검사되고 있으나,
# 추가적으로 forms 안의 clean 함수를 상속하고 재정의하여 유효성 검사를 수행해준다.
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
if username and password:
fcuser = Fcuser.objects.get(username=username)
if not check_password(password, fcuser.password):
self.add_error('password', "비밀번호가 틀렸습니다")
else:
self.user_id = fcuser.id
{% extends "base.html" %}
{% block contents %}
<div class="row mt-5">
<div class="col-12 text-center">
<h1> 로그인 </h1>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
{{ error }}
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<form method="POST" action=".">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
<input type="{{ field.field.widget.input_type }}" class="form-control" id="" placeholder="{{ field.label }}" name="{{ field.name }}" />
</div>
{% if field.errors %}
<span style="color: red">{{ field.errors }}</span>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
{% endblock %}
from .forms import LoginForm
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
request.session['user'] = form.user_id
return redirect('/')
else:
form = LoginForm()
return render(request, 'login.html', {'form': form})