django로 로그인, 회원가입을 구현하는데 두가지 방법이 있었는데, 하나는 말그대로 뷰 자체에서 html에서 post된 유저 정보를 얻어 온 후 채우는 방법이고, 두번째는 forms.py를 생성하는 것이다.
def join(request):
if request.method == 'GET':
return render(request, 'registration/join.html')
elif request.method == 'POST':
userID = request.POST.get('userID', '')
userPW = request.POST.get('userPW1', '')
userName = request.POST.get('userName', '')
usersSubname = request.POST.get('usersSubname', '')
userBirthday =request.POST.get('userBirthday', '')
userGender = request.POST.get('userGender')
#('userID', ' ')는 공백을 default로 한다는 뜻
#하나라도 입력안해서 공백인 상태를 허용하지 않는다
if (userID or userPW or userName or usersSubname or userBirthday or userGender) == '':
return render(request,'registration/join.html')
elif request.POST['userPW1'] != request.POST['userPW2']:
return render(request,'registration/join.html')
else:
user = User(
userID = userID,
userPW = PasswordHasher().hash(userPW),
userName = userName,
usersSubname = usersSubname,
userBirthday = userBirthday,
userGender = userGender
)
user.save()
return render(request, 'registration/complete.html')
장고 폼 기능은 다음 3가지로 요약할 수 있습니다.
- 렌더링을 위해서 데이터를 준비하고 재구성을 해줍니다.
- HTML 폼을 만들어줍니다.
- 클라이언트로부터 제출이 된 데이터를 받고 처리해줍니다.
HTML의 form 태그는 폼 역할의 단지 한 부분의 불과합니다. 하지만 장고에서의 폼 개념은 위에서 설명드린 기능들을 제공합니다. 이런 기능들을 사용하기 위해서 Form Class를 사용해주시면 되는데요.
모델 클래스의 필드는 모델 클래스의 필드가 데이터베이스 필드에 매칭 되는 것처럼, 폼도 폼 필드의 클래스는 html 요소 즉 태그에 매핑이 됩니다. 폼이 제출되면 유효성 검사까지 수행이 됩니다.
즉, Form클래스를 상속받아서 따로 forms.py를 만들어 사용하며,
1.입력폼 HTML 생성( form.as_table(), form.as_p(), form.as_ul() 등)
2.입력폼 값 검증(validation) 및 값 변환
3.검증을 통과한 값들을 사전타입(cleaned_data)으로 제공
등의 역할을 수행한다.
Form 인스턴스는 is_valid() 함수를 갖고 있습니다. is_valid() 함수는 입력받은 폼의 대한 유효성 검사를 실행합니다. is_valid() 함수가 호출되면 값이 유효하다면 참이 리턴되고 cleaned_data에 값이 저장이 됩니다.
app/forms.py
from django import forms
from .models import User
from argon2 import PasswordHasher, exceptions
class LoginForm(forms.Form):
userID = forms.CharField(
max_length=32,
label='userID',
required=True,
widget=forms.TextInput(
attrs={
'class' : 'userID',
'placeholder' : '아이디를 입력해주세요'
}
),
error_messages={'requred' : '아이디를 입력하세요'}
)
userPW = forms.CharField(
max_length=32,
label='userPW',
required=True,
widget=forms.PasswordInput(
attrs={
'class' : 'userPW',
'placeholder' : '비밀번호를 입력해주세요'
}
),
error_messages={'requred' : '비밀번호를 입력하세요'}
)
field_order = [
'userID',
'userPW',
]
def clean(self):
cleaned_data = super().clean()
userID = cleaned_data.get('userID')
userPW = cleaned_data.get('userPW')
if userID and userPW:
try:
user = User.objects.get(userID=userID)
except User.DoesNotExist:
self.add_error('userID', '아이디가 존재하지 않습니다')
return
try:
PasswordHasher().verify(user.userPW, userPW)
except exceptions.VerifyMismatchError:
return self.add_error('userPW', '비밀번호가 다릅니다')
else:
self.userID = user.userID
app/views.py
from .forms import LoginForm
from django.views import generic
from argon2 import PasswordHasher, exceptions
class LoginView(generic.View):
template_name = 'registration/login.html'
form_class = LoginForm
success_url = reverse_lazy("home")
#Class-level 속성을 가지는 객체들은 import 될 때 배치되는데 URL-seolving 규칙은 import 시간에 세팅되어있지 않아 class 내에서 reverse()를 사용하면 URLconf의 규칙을 인식하지 못한다.
loginform = LoginForm()
context = { 'forms' : loginform }
def post(self, request):
loginform = LoginForm(request.POST)
context = { 'forms' : loginform }
if loginform.is_valid():
print(request.user)
self.request.session['user'] = loginform.cleaned_data['userID']
username = self.request.session['user']
# return super().form_valid(form)
return render(request, './home.html', {'username' : username})
else:
context['forms'] = loginform
if loginform.errors:
for value in loginform.errors.values():
context['error'] = value
return render(request, 'registration/login.html', context)
def get(self,request):
return render(request, 'registration/login.html', context=self.context)
Widget
input, textarea 같은 HTML 폼 위젯에 대응되는 클래스로, 해당 위젯을 HTML로 렌더링한다.
Field
각 필드에 대한 유효성을 담당하는 클래스이다. 예) EmailField는 데이터가 유효한 이메일 주소인지 확인한다.
Form
폼 자체에 대한 유효성 검증 규칙 및 HTML로서의 표시 방법을 알고 있는 필드의 모음이다.
Form Media
필요한 CSS와 JS를 제공해준다.
Bound Form
데이터 집합에 바인딩 되어 있으면, 해당 데이터의 유효성을 검사하고 HTML로 렌더링
Unbound Form
유효성을 검사할 데이터가 없으므로 유효성 검사를 하지 못하며 빈 양식을 렌더링
from argon2 import PasswordHasher, exceptions from django.views import generic from django.views.generic import View, RedirectView
pip install argon2-cffi 명령어로 라이브러리 설치해야 한다.
이렇게 암호화해 놓으면, admin 에서 확인해봤을 때 비밀번호가 직접 노출되지 않고 암호화된 키로 변환되어 있는 것을 확인할 수 있다.
참조 블로그
[forms태그로 회원가입 구현] https://arotein.tistory.com/21?category=936406
[forms태그를 쓰는 이유] https://junlab.tistory.com/193
[generic view 적용법] https://ldgeao99.tistory.com/entry/33-app2-generic-view-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
[generic view 종류] https://docs.djangoproject.com/ko/3.0/ref/class-based-views/