2018~/Django 개인 공부 정리
django - 로그인 기능 수정(1) - forms.py 상속, 템플릿 for
반원_SemiCircle
2019. 9. 8. 20:26
1. 목표
- 현재 장고의 로그인을 html에 form 태그를 사용해서 만들었는데, 이를 django에서 제공하는 forms.py를 상속받아 구현해보자.
2.login.html 정리
- 현재 login.html에서 로그인과 관련된 부분을 제거한다.
- 나중에 views.py에서 def login코드도 깨끗하게 정리해야 하는데, 이는 일단 미뤄두자.
<!-- login.html -->
{% 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 %}
<!-- 원래 로그인 form-group이 있었던 곳 -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
{% endblock %}
3. forms.py 생성
- 앱 폴더(fuser)에 forms.py를 생성한다.
4.forms.py 정의
- forms.py에 입력받을 값들에 대해서 Model를 만들어준다.
- from django import forms
- 각 값의 사이즈는 fuser.models.py에서 정의했던 사이즈와 같게 만들어주자.
- Model을 클래스로 정의할 때 forms.Form을 상속받도록 한다.
- split으로 models.py를 놓고 작업하면 편하다.(그냥 필요한 것만 복사해오자.)
- 현재 username과 password란 2필드를 가진 model이 정의되었다.
#forms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(max_length=32)
password = forms.CharField()
5. 뷰 수정
views.py에서 다음처럼 코드를 고쳐, 방금 정의한 model를 화면에 보여주자
방금 정의한 forms.py를 가져오기위해서 from .froms import LoginForm
def login 에서 LoginForm 인스턴스를 생성한다.
생성한 LoginForm 인스턴스를 응답데이터에 넘겨준다. 이 때 데이터 키는 'form'으로 주었다.
기존
def login(request): if request.method=="GET": return render(request,'login.html') elif request.method == "POST" : #전송받은 이메일 비밀번호 확인 username = request.POST.get('username') password = request.POST.get('password') #유효성 처리 res_data ={} if not (username and password): res_data['error']="모든 칸을 다 입력해주세요" else: # 기존(DB)에 있는 Fuser 모델과 같은 값인 걸 가져온다. fuser = Fuser.objects.get(username = username) #(필드명 = 값) # 비밀번호가 맞는지 확인한다. 위에 check_password를 참조 if check_password(password, fuser.password): #응답 데이터 세션에 fuser의 기본키(pk)값인 id 추가. 나중에 쿠키에 저장됨 request.session['user']=fuser.id #리다이렉트 return redirect('/') else: res_data['error'] = "비밀번호가 틀렸습니다." return render(request,'login.html',res_data) #응답 데이터 res_data 전달
변경
def login(request): form = LoginForm() return render(request,'login.html',{'form':form}) #응답 데이터 res_data 전달
6. login.html에 전송한 form 1차 표현
- login.html에서 응답받은 데이터를 표현할 수 있도록 한다.
- 템플릿 표현식인 {{ form }}을 사용하자.
<!-- login.html -->
{% 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 %}
<!-- 원래 로그인 form-group이 있었던 곳 -->
{{ form }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
{% endblock %}
7. 결과
- 값을 입력하지 않으면 알아서 값을 입력해야된다고 나온다.
- 비밀번호가 그대로 노출된다.
8.웹 페이지에서는 응답데이터 활용
- 응답받은 form 모델을 다양한 형태로 출력할 수 있다.
- 예 : {{form.as_p}} - 각 필드 하나하나를 p 태그로 감싼다.
- 예 : {{form.as_table}} - 각 필드를 테이블로 자동 생성해준다.
- 그러나 이렇게 제공하는 기능들로 원하는 페이지를 만들기는 부족하다.
9.템플릿 표현식 for 사용하기
받은 응답데이터를 for문을 이용하여 원하는 형태로 표현해보자.
템플릿 for 표현식은 다음과 같다.(파이썬 for와 유사하다)
{% for 변수명 in 연결형데이터 %} 반복코드 {% endfor %}
먼저 실질적으로 field를 적용하기전 디자인만 추가
10.field를 적용
- 응답데이터의 field를 적용해보자.
- forms.py에서 정의하여 만든 LoginForm에서의 필드들은 여러 속성(변수)들을 가지고 있다.
- .id_for_label : id 입력을 위한 레이블
- .label : 단순 표현을 위한 레이블
- .field.widget.input_type : 해당 필드가 웹 페이지에서 입력받아야 할 input태그의 타입
- .field.name : 해당 field의 name
<div class="row mt-5">
<div class="col-12">
<form method="POST" action=".">
{% csrf_token %}
<!-- 원래 로그인 form-group이 있었던 곳 -->
{% 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="{{field.id_for_label}}"
placeholder="{{field.label}}" name="{{field.name}}">
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
11 원하는 label과 input_type 지정
- forms.py에서 정의했던 field를 재정의 해보자.
- forms.PasswordInput 에는 비밀번호 입력을 위한 widget이 있으며 여기 내부에 textarea 등의 여러 태그들이 미리 정의되있다.
#forms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(max_length=32, label="아이디")
password = forms.CharField(label="비밀번호", widget=forms.PasswordInput )
아직 처리되지 않은 것
- id와 비밀번호 매칭 후 로그인 처리