October
21st,
2017
SignupForm을 사용
member/forms.py
from django import forms
class SignupForm(forms.Form):
username = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control'
}
)
)
password = forms.CharField(
widget=forms.PasswordInput(
attrs={
'class': 'form-control'
}
)
)
member/views.py
def signup(request):
if request.method == "POST":
# 데이터가 binding된 SignupForm인스턴스를 생성
form = SignupForm(request.POST)
# 해당 form이 자신의 필드에 유효한 데이터를 가지고 있는지 유효성 검사
if form.is_valid():
# 통과한 경우 정제된 데이터 (cleaned_data)에서 username과 password 항목을 가져옴
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# 이미 username항목이 주어진 username값으로 존재하는 User가 있는지 검사
if User.objects.filter(username=username).exists():
return HttpResponse(f'Username {username} is already exist')
# username, password가 주어졌고 중복되는 User가 없다면 User생성
user = User.objects.create_user(
username=username,
password=password
)
return HttpResponse(f'{user.username}, {user.password}')
# GET 요청시 SignupForm인스턴스를 form 변수에 할당 context에 같은 키/값으로 전달
form = SignupForm()
context = {
'form': form
}
return render(request, 'member/signup.html', context)
member/signup.html
{% extends 'base.html' %}
{% block content %}
<div class="signup">
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<button class="btn btn-primary btn-block">회원가입</button>
</form>
</div>
{% endblock %}
username field custom validation
member/forms.py
views.py에 있던 username field 중복 검사를 forms.py안의 메소드로 넣어서 is_valid()와 동시에 실행되도록 한다.
from django import forms
from django.contrib.auth import get_user_model
User = get_user_model()
class SignupForm(forms.Form):
username = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control'
}
)
)
password = forms.CharField(
required=False,
widget=forms.PasswordInput(
attrs={
'class': 'form-control'
}
)
)
# is_valid() 할 때 아래 있는 메소드가 한번 돈다.
# clean_<field_name>
def clean_username(self):
data = self.cleaned_data['username']
if User.objects.filter(username=data).exists():
raise forms.ValidationError('Username already exists!')
return data
login 기능 구현
urls.py
url(r'^member/login/$',
member_views.login,
name='login'),
member/views.py
...
from django.shortcuts import render, redirect
from django.contrib.auth import get_user_model, authenticate, login as django_login
...
...
def login(request):
# POST 요청(Form submit)의 경우
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
# 해당하는 User가 있는지 검증
user = authenticate(
username=username,
password=password,
)
# 인증에 성공하면 user변수에 User객체가 할당 실패시 None
if user is not None:
# Django의 Session에 해당 User정보를 추가,
# Response에는 SessionKey값을 Set-Cookie 헤더에 담아 보냄
# 이후 브라우저와의 요청응답에서는 로그인을 유지함
django_login(request, user)
return redirect('post_list')
else:
return HttpResponse('Login credentials invalid!')
else:
# GET요청에서는 Form을 보여줌
return render(request, 'member/login.html')
...
templates/base.html
...
<div class="container">
<a href="{% url 'post_list' %}"><h1>Instagram</h1></a>
<p>
<div> {{ user }} </div>
{% if user.is_authenticated %}
{{ user.username }} 님 환영합니다! [로그아웃]
{% else %}
로그인해주세요
{% endif %}
</p>
<hr>
{% block content %}
{% endblock %}
</div>
...
templates/member/login.html
{% extends 'base.html' %}
{% block content %}
<div>
<form action="" method="POST">
{% csrf_token %}
<input type="text" name="username">
<input type="password" name="password">
<button class="btn btn-primary btn-block">로그인</button>
</form>
</div>
{% endblock%}
Form에 인증 및 로그인 기능을 포함
views.py에 있던 validation 기능들을 forms.py로 옮김
forms.py
class LoginForm(forms.Form):
username = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control'
}
)
)
password = forms.CharField(
widget=forms.PasswordInput(
attrs={
'class': 'form-control'
}
)
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = None
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
self.user = authenticate(
username=username,
password=password
)
if not self.user:
raise forms.ValidationError(
'Invalid login credentials!'
)
else:
# 자기자신에 login() 메서드 추가
setattr(self, 'login', self._login)
def _login(self, request):
django_login(request, self.user)
views.py
이제 views.py는 단순히 폼에 대한 validation check만 진행 후 로그인
def login(request):
# POST 요청(Form submit)의 경우
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
form.login(request)
return redirect('post_list')
else:
return HttpResponse('Login credentials invalid!')
else:
# GET요청에서는 Form을 보여줌
return render(request, 'member/login.html')