미리보는 프로젝트 완성코드 -->https://github.com/leeceo97/python_community
이번 챕터에서 다룰 내용은 기존의 유저 로그인 코드를 장고내의 form기능을 활용하여 리팩토링 하는 과정입니다.
글을 작성하기전 느꼈던 건데 생각보다 이해하기 어려워서 최대한 자세히 작성을 할테니 글이 길어지긴 할텐데 이해한번 해보고 넘어갑시다!! 잘알면 유용한 기능입니다~~
1. forms.py 생성및 기존 코드 삭제및 수정
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 %}
{% 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>
{% if field.errors %}
<span style="color: red">{{ field.errors }}</span>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary">로그인</button>
</form>
</div>
</div>
{% endblock %}
accounts/forms.py(accounts폴더내에 forms.py란 파일 생성후 코드기입해주세요.)
from django import forms
from .models import User
from django.contrib.auth.hashers import check_password
class LoginForm(forms.Form):
useremail = forms.EmailField(
error_messages={
'required': '아이디를 입력해주세요.'
}, max_length=64, label="사용자 이메일")
password = forms.CharField(
error_messages={
'required': '비밀번호를 입력해주세요.'
},widget=forms.PasswordInput, label = "비밀번호")
def clean(self):
cleaned_data = super().clean()
useremail = cleaned_data.get('useremail')
password = cleaned_data.get('password')
if useremail and password:
user = User.objects.get(useremail=useremail)
if not check_password(password, user.password):
self.add_error('password', '비밀번호가 틀립니다.')
else:
self.user_id = user.id
accounts/views.py
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})
하나하나 짚고 넘어가면 일단 forms.py의 기능은 장고 내에 있는 html에서 쓰이는 폼기능들을 백엔드 개발자가 쓰기 편하게 미리 만들어논 기능이라고 보시면 됩니다. 쉽게말해 미리 로그인이나 회원가입에서 필요한 예외처리 패스워드 처리등을 미리 기술 개발을 통해 제공한 것입니다.
-html
html 파일 먼저 보시면 form을 사용하기전에 하나하나 라벨등과 같이 일일이 쳐줬던것과는 달리 장고 템플릿 변수를 사용해 label, widget, error등을 몇줄에 걸쳐 다표현한것을 알수 있습니다. 장고 템플릿 변수에대해 자세히 알고 싶으시면
아래의 사이트에 방문해 알아보시는것도 좋을것 같습니다. html 같은경우는 코드를 다작성하고 나면 알게 되므로 간단히 생략하고 넘어가도록 하겠습니다.
[Django] 템플릿 언어
템플릿 언어를 사용하면 HTML 작업을 훨씬 수월하게 할 수 있다.
velog.io
-forms.py
useremail = forms.EmailField(
error_messages={
'required': '아이디를 입력해주세요.'
}, max_length=64, label="사용자 이메일")
password = forms.CharField(
error_messages={
'required': '비밀번호를 입력해주세요.'
},widget=forms.PasswordInput, label = "비밀번호")
이부분을 먼저 살펴보면 html에서 유효성 검사와 에러메시지등 받아올 데이터들에 대해 useremail, password 필드를 따로 만들어준것이다. 이후 모든 유효성 검사가 끝난 데이터들을 accounts 모델에 저장시키는 것이다. 나머지는 이해 되겠지만 password의 widget같은 경우는 CharField에 위젯을 PasswordInput으로 설정해줌으로써 유저가 비밀번호를 입력할때 가려진 상태로 비밀번호가 입력되게 된다.
def clean(self):
cleaned_data = super().clean()
useremail = cleaned_data.get('useremail')
password = cleaned_data.get('password')
if useremail and password:
user = User.objects.get(useremail=useremail)
if not check_password(password, user.password):
self.add_error('password', '비밀번호가 틀립니다.')
else:
self.user_id = user.id
이부분을 이해하려면 일단 super()가 무엇인지 알아야하는데 이건 오버라이딩의 개념을 알고 있어야 합니다. 아래의 사이트를 참고하시면 됩니다.
[Python] 파이썬 super 기초 개념 및 예제
먼저 super를 사용하기전 상속, 오버라이딩 의 개념이 잡혀있어야 이해하기 쉽습니다. (상속, 오버라이딩 클릭시 페이지 이동) 개념 super() - 자식 클래스에서 부모클래스의 내용을 사용하고 싶을
rednooby.tistory.com
clean함수는 다음과 같은 기능을 합니다.
-User모델에서 기존의 테이블을 불러와 폼에 들어온 데이터와 비교작업
-각종 예외처리에 대한 에러작업
form의 코드를 보면 기존의 view에서 사용하던 기능들을 가져와 처리해줌으로써 view의 코드들이 직관적으로 비즈니스 기능들만 수행하도록 하는 역할을 한다는걸 알수 있습니다.
-views.py
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})
기존의 views.py의 코드와는 다르게 많이 간단해진걸 알수가 있습니다. 여기서 궁금한것은 is_valid()였습니다.
def is_valid(self):
"""Return True if the form has no errors, or False otherwise."""
return self.is_bound and not self.errors
is_valid함수를 찾아보니 위와 같이 에러가 없을경우 참값을 반환한다는 걸 알수 있습니다. 즉, forms.py의 유효성 검사를 모두 거쳐야지 다음의 조건을 수행하도록 해준다는 함수임을 알수 있습니다.
2. 마무리 멘트
이번 form은 사실 너무 이해하기가 힘든 챕터였습니다. 오버라이딩의 개념도 제대로 이해하지 못했고 is_valid와 clean()등 이게 뭘뜻하는지 내장된 함수인지 조차 잘모르겠어서 난해했는데 하나하나 파고 들어보니 이해가 갔고 다시한번 파이썬 기본문법의 중요성을 알수있는 챕터였다고 느껴집니다. 한가지 팁을 알려드리면 이게 장고에 내장되어있는 기능인지 확인해보는 방법은 아래의 이미지와 같이 헷갈리는 변수에 오른쪽 클릭을하고 Go to Definition을 클릭하면 그함수 또는 클래스가 어떻게 이루어져있는지 보여주니 보고 참고하셔서 개발하시면 될겁니다!! 감사합니다:)
'기술 > Django' 카테고리의 다른 글
django 커뮤니티 만들기-(6)게시판(form ,view) (0) | 2021.06.01 |
---|---|
django 커뮤니티 만들기-(5)게시판 구현(templates, url) (0) | 2021.06.01 |
django 커뮤니티 만들기-(3)회원가입, 로그인 구현(views.py) (0) | 2021.05.26 |
django 커뮤니티 만들기-(2)회원가입, 로그인 구현(templates, urls.py) (0) | 2021.05.25 |
django 커뮤니티 만들기-(1)프로젝트, 앱 생성 및 모델 적용 (0) | 2021.05.25 |