회원 가입, 로그인 기능 등
유저 기능을 구현하기 위해 가상 프로젝트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주이며, 설정은초 단위로 가능하다.