User object
와 Web request
에 대한 인증시스템으로 구성AuthenticationForm
은 forms.form
의 상속을 받아 만들어지게된다.request.user
를 제공request.user
는 현재 사용자가 로그인하지 않은 경우 AnonymousUser
클래스의 인스턴스로 설정되며, 그렇지 않으면 User
클래스의 인스턴스로 설정됨프로젝트.settings.py
에서 TEMPLATES.OPTIONS.context_processors
에서 확인할 수 있다.'django.template.context_processors.request',
sessionid
를 삭제HTTP 쿠키 : 클라이언트의 로컬에 저장
되는 키-값의 작은 데이터 파일
세션을 유지하는 방식 중 가장 대표적인 방식
웹 페이지에 접속하면 요청한 웹 페이지를 받으며 쿠키를 로컬에 저장하고, 클라이언트가 재요청시마다 웹 페이지 요청과 함께 쿠키 값도 같이 전송
쿠키 확인
F12 - Application - Storage - Cookies
사용 목적
HTTP 쿠키는 상태가 있는 세션을 만들도록 해준다.
Cookie lifetime(라이프타임, 일생) - 파기시점 존재 유무로 구분
Expires
속성에 지정된 날짜 혹은 Max-Age 속성에 지정된 기간이 지나면 삭제프로젝트.settings.py
에서 SESSION_COOKIE_AGE 로 쿠키 유통기한 설정 가능
DAY_IN_SECONDS = 86400 # 가독성을 좋게 하기 위한 변수
SESSION_COOKIE_AGE = DAY_IN_SECONDS * 2 # 그냥 132800 로 입력해도 되지만, 이렇게 표기하면 더 가독성이 좋아짐
서버에 session id를 쿠키를 사용해 클라이언트 로컬에 저장
, 클라이언트가 다시 서버에 접속할 때 해당 쿠키(session id가 저장된)를 이용해 서버에 session id를 전달get_user_model()
을 이용해서 참조로그인 Session(이하 세션)을 Create하는 로직과 같음
login()
계정관리 app 만들기
python manage.py startapp accounts
프로젝트.settings.py
> INSTALLED_APPS 에 추가
accounts/urls.py
만들기
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
,
]
프로젝트/urls.py
에 연결
path('accounts/', include('accounts.urls')),
accounts/urls.py
path('login/', views.login, name='login'),
추가accounts/views.py
form = AuthenticationForm(request, data = request.POST)
auth_login(request, form.get_user())
from django.shortcuts import render, redirect
from django.contrib.auth import login as auth_login # login함수와 이름이 겹쳐서
from django.contrib.auth.forms import AuthenticationForm
# Create your views here.
def login(request) :
if request.method=='POST' :
# data는 forms.form 두번쨰 인자이므로 data = 은 생략 가능
form = AuthenticationForm(request, data = request.POST) # 먼저 request 인자를 받아야함
if form.is_valid() :
# 세션 CREATE/ form.get_user는 User 객체 반환
auth_login(request, form.get_user())
return redirect('articles:index') # 로그인 성공시 메인페이지 이동
else :
form = AuthenticationForm()
context = {
'form' : form,
}
return render(request, 'accounts/login.html', context)
accounts/templates/accounts
에 login.html
만들기
username
password
로 name을 가짐{% extends 'base.html' %}
{% block content %}
<h1> 로그인 </h1>
<form action="{% url 'accounts:login' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock content %}
{{ request.user }}
로그인 하기 이전
로그인 하기
data Table 보기
django_session
테이블이 생성됨어플.urls.py
path('logout/', views.logout, name='logout')
어플.views.py
from django.views.decorators.http import require_POST
from django.contrib.auth import logout as auth_logout
@require_POST
def logout(request) :
auth_logout(request)
return redirect('articles:index')
base.HTML
에 버튼 넣어주기
request.user.is_authenticated
{% if request.user.is_authenticated %}
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="Logout">
</form>
{% else %}
<a href="{% url 'accounts:login' %}">Login</a>
{% endif %}
is_authenticated
: attribute 사용True
이며, AnomymousUser에 대해서만 항상 False
login_required
: decorator 사용'/accounts/login/'
accounts
로 설정한 이유 중 하나임로그인 한 상태에서 로그인 페이지 접근 막기 - accounts.views.py
def login(request) :
if request.user.is_authenticated :
return redirect('articles:index')
"""
내용
"""
로그인 안한 상태에서 글쓰기 막기 - index.html
<h1>Articles</h1>
{% if request.user.is_authenticated %}
<a href="{% url 'articles:create' %}">[CREATE]</a>
{% else %}
<a href="{% url 'accounts:login' %}">[새 글을 작성하려면 로그인하세요]</a>
{% endif %}
2-2. 로그인 안한 상태에서 글쓰기 막기 - 어플.views.py
@login_required
달아주기from django.contrib.auth.decorators import login_required
@login_required
@require_http_methods(['GET', 'POST'])
def create(request):
# 내용
2-3. 글쓰기에서 넘어온 url 처리 - accounts.views.py
login_required
로 인해 보내진 주소는 http://127.0.0.1:8000/accounts/login/?next=/articles/create/
형태를 띄고 있음redirect(request.GET.get('next') or 'articles:index')
next가 있다면 넘어갈 수 있도록 redirect 수정def login(request) :
if request.method=='POST' :
# data는 forms.form 두번쨰 인자이므로 data = 은 생략 가능
form = AuthenticationForm(request, data = request.POST) # 먼저 request 인자를 받아야함
if form.is_valid() :
# 세션 CREATE/ form.get_user는 User 객체 반환
auth_login(request, form.get_user())
return redirect(request.GET.get('next') or 'articles:index') # 로그인 성공시 메인페이지 이동
글삭제 - 어플.views.py
@login_required
와 @require_POST
를 같이 쓰게 되면redirect(request.GET.get('next'))
을 통해서 GET 방식으로 되돌아가기 때문에 생기는 로직상의 에러@login_require
대신 request.user.is_authenticated
사용하기@require_POST
def delete(request, pk) :
if request.user.is_authenticated :
article = get_boject_or_404(Article, pk=pk)
article.delete()
return redirect('articles:index')
accounts.urls.py
에서 로그인 url 추가
path('signup/', views.signup, name='signup')
accounts.views.py
에서 signup 함수 추가
form = UserCreationForm()
user = form.save()
회원가입 이후 auth_login(request, user)
로그인까지 처리from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login as auth_login
def signup(request) :
if request.method== "POST" :
form = UserCreationForm(request.POST)
if form.is_valid() :
user = form.save()
auth_login(request, user)
return redirect('articles:index')
else : # 회원가입 페이지 첫 접근
form = UserCreationForm()
context = {
'form' : form,
}
return render(request, 'accounts/signup.html', context)
signup.html
만들기{% extends 'base.html' %}
{% block content %}
<h1> 회원가입 </h1>
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock content %}
base.html
에 링크 추가
{% else %}
<a href="{% url 'accounts:login' %}">Login</a>
<a href="{% url 'accounts:signup' %}">Signup</a>
{% endif %}
accounts.urls.py
에서 로그인 url 추가path('delete/', views.delete, name='delete')
accounts.views.py
에서 delete함수 추가
@required_POST
def delete(request) :
if request.user.is_authenticated :
request.user.delete()
auth_logout(request) # 세션 지워주기
return redirect('articles:index')
base.html
에 링크 추가
{% if request.user.is_authenticated %}
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="Logout">
</form>
<form action="{% url 'accounts:delete' %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴">
</form>
{% else %}
<a href="{% url 'accounts:login' %}">Login</a>
<a href="{% url 'accounts:signup' %}">Signup</a>
{% endif %}
accounts.urls.py
에서 로그인 url 추가
path('update/', views.update, name='update')
accounts.views.py
에서 update함수 추가
from django.contrib.auth.forms import UserChangeForm
def update(request) :
if request.method == "POST" :
pass
else :
form = UserChangeForm()
context = {
'form' : form,
}
return render(request, 'accounts/update.html', context)
update.html
만들기{% extends 'base.html' %}
{% block content %}
<h1> 회원수정 </h1>
<form action="{% url 'accounts:login' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock content %}
3-2 . accounts.forms.py
get_user_model()
from django.contrib.auth.forms import UserChangeForm
# from django.contrib.auth.models import User # 이렇게 직접적으로 참고할수는 있으나 권장하지 않는 방법임
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm) :
class Meta :
# model = User
model = get_user_model()
field= ('email', 'first_name', 'last_name', 'password')
accounts.views.py
에서 update함수 수정
form = CustomUserChangeForm(request.POST, instance=request.user)
from .forms import CustomUserChangeForm
from django.contrib.auth.decorators import login_required
@login_required
def update(request) :
if request.method == "POST" :
form = CustomUserChangeForm(request.POST, instance=request.user)
if form.is_valid() :
form.save()
return redirect('articles:index')
else :
form = CustomUserChangeForm(instance=request.user)
context = {
'form' : form,
}
return render(request, 'accounts/update.html', context)
base.html
추가<a href="{% url 'accounts:update' %}">[회원정보수정]</a>
{% if request.user.is_authenticated %}
<a href="{% url 'accounts:update' %}">[회원정보수정]</a>
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="Logout">
</form>
<form action="{% url 'accounts:delete' %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴">
</form>
{% else %}
<a href="{% url 'accounts:login' %}">Login</a>
<a href="{% url 'accounts:signup' %}">Signup</a>
{% endif %}
accounts/password/
로 자동 연결됨urls.py
에서 path('password/', views.update_password, name='update_password'),
views.py
PasswordChangeForm(request.user, request.POST)
update_session_auth_hash(request, form.user) # session 을 update
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
def update_password(request) :
if request.method == "POST" :
form =PasswordChangeForm(request.user, request.POST)
if form.is_valid() :
user = form.save() # 이때 로그아웃처리됨. session 정보 날라가고, 로그인정보도 사라짐
update_session_auth_hash(request, user) # session 을 update 이렇게 해야 비밀번호를 바꾸더라도 로그아웃이 되지 않음
return redirect('articles:index')
else :
form = PasswordChangeForm(request.user)
context = {
'form':form,
}
return render(request, 'accounts/update_password.html', context)
안녕하세요. 혹시 이 글에 대한 깃헙 링크가 있나요? base.html이 어디있는지 모르겠어서요 ㅠㅠ