요모조모 ʚɞ

[D.R.F] 커스텀 유저 구현하기 - 회원가입, 로그인 본문

개발/Django RESTful API

[D.R.F] 커스텀 유저 구현하기 - 회원가입, 로그인

Angela_OH 2021. 2. 18. 01:00

 

안녕하세요 (._. )>

오늘은 Django RESTful API로 회원정보를 관리(회원가입/로그인) 해보도록 하겠습니다.

 

Django에서는 기본적으로 사용자 모델인 User 모델을 제공하고 있습니다.

하지만 임의로 원하는 필드(ex. 닉네임이나 생일 등)를 가진 사용자 모델을 사용하기 위해서는

custom user 모델을 구현해야 합니다!

Djago의 custom user에 관한 내용은 아래의 공식 문서를 참고하였습니다.

docs.djangoproject.com/en/3.1/topics/auth/customizing/

 

Customizing authentication in Django | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

custom user 모델을 구현하기 위해서는 BaseUserManagerAbstractBaseUser 클래스를 상속받아 새롭게 구현해야 합니다.

여기서 BaseUserManager는 유저를 생성하는 역할을 하는 헬퍼 클래스이고,

AbstractBaseUser는 실제 모델이 상속받아 생성하는 클래스입니다.

 

그럼 custom user 코드를 작성해보도록 하겠습니다.

우선 custom user과 관련된 기능을 하는 account라는 이름의 앱을 만들어줍니다.

python manage.py startapp account

 

settings.py

settings.py에서 방금 생성한 account 앱을 등록해줍니다.

...
INSTALLED_APPS = [
	...
    'account',
 ]
 ...

 

models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class UserManager(BaseUserManager):
    # 일반 user 생성
    def create_user(self, email, nickname, name, password=None):
        if not email:
            raise ValueError('must have user email')
        if not nickname:
            raise ValueError('must have user nickname')
        if not name:
            raise ValueError('must have user name')
        user = self.model(
            email = self.normalize_email(email),
            nickname = nickname,
            name = name
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    # 관리자 user 생성
    def create_superuser(self, email, nickname, name, password=None):
        user = self.create_user(
            email,
            password = password,
            nickname = nickname,
            name = name
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class User(AbstractBaseUser):
    id = models.AutoField(primary_key=True)
    email = models.EmailField(default='', max_length=100, null=False, blank=False, unique=True)
    nickname = models.CharField(default='', max_length=100, null=False, blank=False, unique=True)
    name = models.CharField(default='', max_length=100, null=False, blank=False)
    
    # User 모델의 필수 field
    is_active = models.BooleanField(default=True)    
    is_admin = models.BooleanField(default=False)
    
    # 헬퍼 클래스 사용
    objects = UserManager()

    # 사용자의 username field는 nickname으로 설정
    USERNAME_FIELD = 'nickname'
    # 필수로 작성해야하는 field
    REQUIRED_FIELDS = ['email', 'name']

    def __str__(self):
        return self.nickname

 

지금부터 custom user 모델을 생성하도록 하겠습니다.

저는 헬퍼 클래스인 UserManager 클래스에서 create_usercreate_superuser 함수를 통해

일반 user관리자 user 객체를 생성하는 코드를 작성해주었습니다. (is_admin의 차이)

AbstractUser인 User 클래스에서는 사용자 모델에 필요한 field를 작성해주었고, 

USERNAME_FIELD, REQUIRED_FIELDS를 설정해주었습니다.

참고로 is_activeis_admin field는 Django User 모델의 필수 field라고 합니다!

 

custom user 모델을 생성해준 이후, 마이그레이션을 진행합니다.

python manage.py makemigrations
python manage.py migrate

 

serializers.py
from .models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        user = User.objects.create_user(
            email = validated_data['email'],
            nickname = validated_data['nickname'],
            name = validated_data['name'],
            password = validated_data['password']
        )
        return user
    class Meta:
        model = User
        fields = ['nickname', 'email', 'name', 'password']

 

다음으로는 생성한 User 모델을 기반으로 serializer를 작성해주었습니다.

serializer의 field로는 회원가입 시 입력을 받고자 하는 nickname, email, name, password로 설정하였습니다.

UserSerializer에서는 한 가지 주의해야 할 점이 있는데,

바로 create 시 (회원가입 시) 입력받은 데이터를 검증해주어야 한다는 것입니다.

(유효하지 않은 값의 입력을 방지하기 위해)

따라서 저는 create 함수를 overriding 한 후 validated_data(유효성 검증을 통과한 값)를 기반으로 User 객체를 생성해주었습니다.

 

views.py
from django.shortcuts import render
from .serializers import UserSerializer
from .models import User
from rest_framework import generics

# 회원가입
class UserCreate(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

 

이후 생성한 User 모델과 UserSerializer를 기반으로 views.py를 작성해주었습니다.

회원가입은 객체를 생성하는 역할을 하기 때문에 generics.py의 CreateAPIView를 상속받아 사용하였습니다.

지난번에 실습했던 것과 유사하게 queryset으로는 User 객체를,

serializer_class로는 UserSerializer를 전달해주었습니다.

 

urls.py

● account app 내부 urls.py

from django.urls import path, include
from . import views
from rest_framework import urls

urlpatterns =[
    path('signup/', views.UserCreate.as_view()),
    path('api-auth/', include('rest_framework.urls')),
 ]

 

● 프로젝트 폴더 내부 urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('user/', include('account.urls')),
    ...
 ]

 

마지막으로는 현재까지 작성한 views.py를 바탕으로 url을 작성하였습니다.

회원가입을 의미하는 UserCreate를 추가해주었고,

로그인을 위해서는 rest_framework에서 제공하는 기능을 활용해주었습니다.

저는 보통 로그인 기능을 사용하지 않고, JWT token으로 사용자를 구분하기 때문에

해당 기능은 편의상 추가해주었습니다.

 

이렇게 코드 작성을 완료하였다면 서버를 실행시켜줍니다.

python manage.py runserver

 

127.0.0.1:8000/user/signup

 

서버 실행 후 127.0.0.1:8000/user/signup으로 접속하면 위의 사진과 같이 회원가입을 할 수 있는 화면이 보입니다.

정상적으로 회원 가입을 진행한 후 우측 상단의 Log in 항목을 클릭하면, 아래와 같이 로그인 기능을 사용할 수 있습니다.

 

127.0.01:8000/user/api-auth

 

마지막으로 생성되어 있는 User 목록을 확인하기 위해 Django shell에 접속해줍니다.

python manage.py shell

 

이후 User 모델을 import 해주면 User 객체를 확인해볼 수 있습니다!

from account.models import User
User.objects.all()

 

저는 회원가입을 여러 번 해봤더니 6개 정도의 User 객체가 생성되었네요 ^0^

Django shell

 

이상으로 Django Restful API로 회원가입, 로그인 기능을 구현해보았습니다!

다음번에는 본격적인 게시판 기능 구현하기를 해보도록 하겠습니다 :D

블로그에 밀린 것들 얼른 정리하고 싶은데 ,,, 체력과 시간이 따라주지 않네요 ㅠ^ㅠ

 

Comments