config/urls.py
...
urlpatterns=[... path("users/", include("users.urls", namespace="users")),]
templates/partials/nav.html
<a href="{% url "core:home" %}">Nbnb</a>
<ul>
<li><a href="{% url "users:login" %}">Login</a></li>
</ul>
users/urls.py
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [
path("login", views.LoginView.as_view(), name="login"),
path("logout", views.log_out, name="logout"),
]
templates/users/login.html
{% extends "base.html" %}
{% block page_title %}
Log In
{% endblock page_title %}
{% block search-bar %}
{% endblock search-bar %}
{% block content %}
Hello!
{% endblock content %}
users/views.py
from django.views import View
from django.views.generic import FormView #FormView import
from django.urls import reverse_lazy
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login, logout
from . import forms
class LoginView(FormView):
template_name = "users/login.html" #rendering되는 html
form_class = forms.LoginForm #사용할 Form 지정
success_url = reverse_lazy("core:home") #인증완료 시 이동할 경로 지정
def form_valid(self, form): #내장 method인 form_valid를 통해 유효성 검사 진행
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(self.request, username=email, password=password)
if user is not None:
login(self.request, user)
return super().form_valid(form)
def log_out(request):
logout(request)
return redirect(reverse("core:home"))
users/forms.py
from django import forms
from . import models
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
email = self.cleaned_data.get("email") # 👈 유효성 검사를 진행한 email field에 값을 추출한다.
password = self.cleaned_data.get("password") # 👈 유효성 검사를 진행한 password field에 값을 추출한다.
try:
user = models.User.objects.get(email=email) # 👈 emil을 기준으로 해당 Object를 가져온다.
if user.check_password(password): # 👈 비밀번호가 서로 일치하다면 True, 아니면 False 반환
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError("Password is wrong"))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError("User does not exist"))
templates/partials/nav.html
<a href="{% url "core:home" %}">Nbnb</a>
<ul>
{% if user.is_authenticated %}
<li><a href="{% url "users:logout" %}">Log out</a></li>
{% else %}
<li><a href="{% url "users:login" %}">Log in</a></li>
<li><a href="{% url "users:signup" %}">Sign up</a></li> #다음과 같이 추가, 로그인 된 상태에서는 보일 필요가 없음
{% endif %}
</ul>
templates/users/signup.html
{% extends "base.html" %}
{% block page_title %}
Sign Up
{% endblock page_title %}
{% block search-bar %}
{% endblock search-bar %}
{% block content %}
<form method="POST" action="{% url "users:signup" %}">
{% csrf_token %} #서버의 보안을 위해 POST로 데이터를 전송할 때는 {% csrf_token %}을 반드시 넣어줘야한다. 넣지 않으면 에러가 발생한다
{{form.as_p}}
<button>Sign up</button>
</form>
{% endblock content %}
users/forms.py
from django import forms
from . import models
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
try:
user = models.User.objects.get(email=email)
if user.check_password(password):
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError("Password is wrong"))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError("User does not exist"))
class SignUpForm(forms.Form):
first_name = forms.CharField(max_length=80)
last_name = forms.CharField(max_length=80)
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
password1 = forms.CharField(widget=forms.PasswordInput, label="Confirm Password")
def clean_email(self):
email = self.cleaned_data.get("email") #field의 입력값 가져오기
try:
models.User.objects.get(email=email) #필드의 email값이 DB에 존재하는지 확인
raise forms.ValidationError("User already exists with that email")
except models.User.DoesNotExist:
return email #존재하지 않는다면, 데이터를 반환시킨다.
def clean_password1(self):
password = self.cleaned_data.get("password")
password1 = self.cleaned_data.get("password1")
if password != password1:
raise forms.ValidationError("Password confirmation does not match")
else:
return password
# save method로 DB에 저장
def save(self):
first_name = self.cleaned_data.get("first_name")
last_name = self.cleaned_data.get("last_name")
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
user = models.User.objects.create_user(email, email, password)
#"create_user"는 id, email, password를 순서대로 전달해줘야 한다.
user.first_name = first_name
user.last_name = last_name
user.save()
users/urls.py
urlpatterns = [
path("login", views.LoginView.as_view(), name="login"),
path("logout", views.log_out, name="logout"),
path("sigup", views.SignUpView.as_view(), name="signup"), #다음과 같이 추가
]
users/views.py
from django.views.generic import FormView
from django.urls import reverse_lazy
from django.shortcuts import redirect, reverse
from django.contrib.auth import authenticate, login, logout
from . import forms
class LoginView(FormView):
template_name = "users/login.html"
form_class = forms.LoginForm
success_url = reverse_lazy("core:home")
def form_valid(self, form):
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(self.request, username=email, password=password)
if user is not None:
login(self.request, user)
return super().form_valid(form)
def log_out(request):
logout(request)
return redirect(reverse("core:home"))
class SignUpView(FormView):
template_name = "users/signup.html"
form_class = forms.SignUpForm
success_url = reverse_lazy("core:home")
...
def form_valid(self, form):
form.save()
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(self.request, username=email, password=password)
if user is not None:
login(self.request, user)
return super().form_valid(form)
users/forms.py
from django import forms
from . import models
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
try:
user = models.User.objects.get(email=email)
if user.check_password(password):
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError("Password is wrong"))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError("User does not exist"))
class SignUpForm(forms.ModelForm): # ModelForm을 상속하면 Model을 활용할 수 있음.
class Meta: # 연결할 Model과 사용할 fields를 지정
model = models.User
fields = ("first_name", "last_name", "email")
password = forms.CharField(widget=forms.PasswordInput)
password1 = forms.CharField(widget=forms.PasswordInput, label="Confirm Password")
def clean_password1(self):
password = self.cleaned_data.get("password")
password1 = self.cleaned_data.get("password1")
if password != password1:
raise forms.ValidationError("Password confirmation does not match")
else:
return password
def save(self, *args, **kwargs):
user = super().save(commit=False) # "commit=False"는 Object는 생성하지만 저장하지 않은 상태
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
user.username = email
user.set_password(password) # set_password는 비밀번호를 hash값으로 변경
user.save()