회원 가입, 로그인 기능 등
유저 기능
을 구현하기 위해 가상 프로젝트our_school_now_is
를 시작한다.
본 프로젝트의 유저 기능을 구현하기 위해
유저 모델
은contrib.auth
의models
를 사용하고, 나머지 기능은allauth
패키지를 통해 구현한다.
allauth
는contrib.auth
가 지원하지 않는이메일 인증
,소셜 로그인
기능을 지원한다.
또한
allauth
은 유저기능이 이미 완성되어 있지만contrib_auth
는 필요한 기능을 모두 직접 구현해야 한다.
따라서
유저 모델
은contrib.auth
를 통해, 기능은allauth
를 통해 구현한다.
개발환경은
<dear>
프로젝트에 적용된 개발환경을 사용한다. 프로젝트 루트 디렉토리는Our_school_now_is
이며, 생성한 앱은our_school
이다.
생성한
our_school
앱을 프로젝트 구성 디렉토리의settings.py
에 등록한다.
User
모델 클래스를 생성한다. 모델은AbstractUser
를 상속받는다.
#models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
pass
지금 당장은 필드를 추가하지 않기 떄문에
pass
를 작성한다.
프로젝트 구성 디렉토리의
settings.py
에서our_school
앱의User
모델을 본 프로젝트의 유저 모델로 사용한다는 것을 정의한다.
#settings.py
AUTH_USER_MODEL = 'our_school.User'
유저 모델을 등록해야
allauth
패키지가 해당 모델을 사용할 수 있다.
모델이 변경되었으니
makemigrations
과migrate
를 해준다.
our_school
앱의admin.py
에User
모델을 등록한다.
#admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
# Register your models here.
admin.site.register(User, UserAdmin)
User
모델을 불러오고,User
모델에 대한 관리자 인터페이스를 제공하는UserAdmin
을 불러온다. 이후User
모델과,UserAdmin
클래스를 등록한다.
슈퍼유저
계정을 생성한 뒤관리자 페이지
로 접속해보면User
관리자 페이지를 확인할 수 있다.
명령어를 통해
allauth
를 설치한다.
pip install django-allauth
이후
settings.py
에 아래의 코드를 추가한다.
#settings.py
AUTHENTICATION_BACKENDS = [
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by email
'allauth.account.auth_backends.AuthenticationBackend',
]
이후
settings.py
의INSTALLED_APPS
에 다음 항목들을 추가한다. 만약 일치하는 코드가 이미 작성되어 있다면 추가하지 않는다.
#settings.py
INSTALLED_APPS = [
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
]
이후
INSTALLED_APPS
하단에 다음 항목을 추가한다.
#settings.py
SITE_ID = 1
이후 다음 코드를 추가한다.
# settings.py
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
본인은 아래와 같은 에러가 나타났다.
Watching for file changes with StatReloader Exception in thread django-main-thread: Traceback (most recent call last): File "/Users/gwon-uihyeon/.pyenv/versions/3.9.4/lib/python3.9/threading.py", line 954, in _bootstrap_inner self.run() File "/Users/gwon-uihyeon/.pyenv/versions/3.9.4/lib/python3.9/threading.py", line 892, in run self._target(*self._args, **self._kwargs) File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/utils/autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 125, in inner_run autoreload.raise_last_exception() File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/utils/autoreload.py", line 87, in raise_last_exception raise _exception[1] File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/core/management/__init__.py", line 394, in execute autoreload.check_errors(django.setup)() File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/utils/autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/__init__.py", line 24, in setup apps.populate(settings.INSTALLED_APPS) File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/django/apps/registry.py", line 124, in populate app_config.ready() File "/Users/gwon-uihyeon/.pyenv/versions/django-envs/lib/python3.9/site-packages/allauth/account/apps.py", line 17, in ready raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: allauth.account.middleware.AccountMiddleware must be added to settings.MIDDLEWARE
구글링을 통해 해결했다.
settings.py
의MIDDLEWARE
에 아래의 코드를 추가했다.
#settings.py
MIDDLEWARE = [
'allauth.account.middleware.AccountMiddleware',
]
프로젝트 구성 디렉토리의
urls.py
파일을 수정한다.
url이 비어있는 경우, allauth.urls를 참조하는 코드를 추가했다.
#urls.py
from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("allauth.urls"))
]
에러를 방지하기 위해 다시한 번
makemigrations
와migrate
를 진행한다.
개발 서버 실행 후
/login
에 접속하면 아래와 같이 로그인, 비밀번호 찾기, 회원가입 페이지를 확인할 수 있다.
allauth
를 통해 생성된 것을 확인할 수 있다.
회원가입을 진행하면 url 상에서는
/profile
로 이동되지만404에러
가 발생되는 것을 알 수 있다.
이번에는 회원가입 후
홈페이지
를 리다이렉션 하는 기능을 알아본다.
프로젝트 구성 디렉토리의
urls.py
를 다음과 같이 수정한다.
#urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("our_school.urls")), #추가
path('', include("allauth.urls"))
]
이 경우
비어있는 url 접근 시
, 상단에 있는our_school.urls
를 먼저 확인한 뒤, 일치하는 url이 없다면 다시allauth.urls
를 확인한다. 만약 그래도 없다면404 에러
를 발생시킨다.
다음으로
our_school
앱의urls.py
를 생성한다.
#ulrs.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name="index"),
]
index
뷰를 생성한다.
# views.py
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, "our_school/index.html")
index.html
템플릿을 생성한다.
<!--index.html-->
<h1>홈페이지</h1>
현재는
로그인이 성공
하면account/profile
로 이동되도록기본값
이 설정되어 있다.allauth
의기본값
을 변경하기 위해서는settings.py
의allauth
세팅을 추가하면 된다.
allauth
의 세팅은 너무 다양해서 본 문서를 참고하고, 필요한 기능을 그때 그때 찾아서 사용하면 된다.
우리가 해야할 일은
로그인 성공 시
,account/profile
이 아닌,index(url name)
로 이동하도록 변경하는 것이다.settings.py
에서 설정하는 방법은 아래와 같다.
#settings.py
ACCOUNT_SIGNUP_REDIRECT_URL = "index"
LOGIN_REDIRECT_URL = "index"
이렇게 하면 로그인 시, 또는 회원가입 시
index(url name)
으로 이동하는 것으로 변경된다.
현재는 로그인한 유저 정보와, 로그아웃 버튼이 없다. 만들어보자.
현재 로그인된 유저의 데이터를
view
에서는request.user
로,템플릿
에서는{{ user }}
로 접근할 수 있다.
.is_authenticated
속성을 사용하면, 현재 유저가 로그인 했는지 아닌지를 판단할 수 있다.
index.html
템플릿을 다음과 같이 변경한다.
<!--index.html-->
<h1>홈페이지</h1>
{% if user.is_authenticated %}
<p>반갑습니다 {{ user }} 님</p>
{% else %}
<p>로그인이 필요합니다.</p>
{% endif %}
<navbar>
{% if user.is_authenticated %}
<a href="{% url "account_logout" %}">로그아웃</a>
{% else %}
<a href="{% url "account_login" %}">로그인</a>
<a href="{% url "account_signup" %}">회원가입</a>
{% endif %}
</navbar>
살펴보면
if
문으로 user가 로그인 한 경우와 그렇지 않은 경우를 구분했다.
또한 로그아웃, 로그인, 회원가입으로 이동하는
<a>
태그를 추가했는데,allauth
에서 사용하는 url 정보를 확인하려면 allauth 소스코드를 참고하면 된다.
현재 페이지는 로그아웃 버튼 클릭 시, 로그아웃 페이지로 이동한다. 로그아웃 버튼 클릭 시 바로 로그아웃되는 기능을 구현하려면
allauth
의 세팅을 추가해야 한다.
#settings.py
ACCOUNT_LOGOUT_ON_GET = "True"
우리가 페이지에 로그인 하면 다른 페이지에 다녀와도 로그인 상태가 유지되는 경우가 잦다. 이와 관련하여 세션 개념을 알아본다.
클라이언트에서 로그인하면 서버에서는
세션ID
를 생성한다. 세션ID에는 유저와 관련된 정보들이 담겨있다. 이후 서버는 세션ID를 클라이언트에게쿠키
를 통해 전달하는데, 이후 클라이언트의 요청은 서버로부터 생성된 세션ID를 포함하고 있어 서버는 해당 세션ID를 통해 해당 유저가 로그인된 상태임을 판단한다.
로그인 정보 기억하기
기능은 웹 브라우저를 종료해도세션 쿠키
를 유지할 것인지 아닌지를 정하는 기능이다.
allauth
에서는 세션 쿠키를 유지할 것인지 아닌지를 설정하는 것 외에도 세션 쿠키의유효시간
을 직접 설정할 수도 있다.기본값은 2주
이며, 설정은초 단위
로 가능하다.