django, drf

dj-rest-auth/allauth를 이용한 회원가입기능 구현

땅콩콩 2022. 8. 4. 03:03

이번 프로젝트에서는 drf와 react를 사용하고, 로그인 회원가입 기능도 dj-rest-auth와 alllauth를 사용해서 구현한다.

drf를 처음 사용해봐서 지금 당장은 어려움이 있지만 또 하다보면 익숙해진다고 생각하고 열심히 해봐야겠다!

 

우선 models.py부터 보자!

여기선 다양한 필드를 받아야 하기 때문에 AbstractUser를 상속해서 유저를 확장해줬다.

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    username = None
    email = models.EmailField(max_length=255, unique=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    
    objects = UserManager()

    realname = models.CharField(max_length=50, blank=True)
    nickname = models.CharField(max_length=50, blank=True)
    address = models.CharField(max_length=200, blank=True)
    phone = models.CharField(max_length=100, blank=True)
    height = models.DecimalField(max_digits=4, decimal_places=1, default=0)
    weight = models.DecimalField(max_digits=4, decimal_places=1, default=0)

    def __str__(self):
            return self.email

다음은 urls.py이다. 다른 경로는 신경안써도 되고 dj-rest-auth부분만 보면 된다.

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('dj-rest-auth/', include('dj_rest_auth.urls')),
    path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
    path('accounts/', include('allauth.urls')),
    path('accounts/', include('accounts.urls')),
]

다음은 대망의 serializers.py이다.

 

serializer는 간단하게 말하면 장고의 form과 비슷한데, 데이터를 직렬화해서 json형식으로 넘겨주는 녀석이다!

나는 우선 기본 serializers를 상속받아서 SignUpSerializer를 만들어주고, 그 안에 get_cleaned_data()와 save() 메소드를 오버라이딩했다.

 

오버라이딩할때 상속받은 클래스는 dj-rest-auth 공식 github에서 참고했다.

https://github.com/iMerica/dj-rest-auth/blob/bf168d9830ca2e6fde56f83f46fe48ab0adc8877/dj_rest_auth/registration/serializers.py#L12

 

GitHub - iMerica/dj-rest-auth: Authentication for Django Rest Framework

Authentication for Django Rest Framework. Contribute to iMerica/dj-rest-auth development by creating an account on GitHub.

github.com

또, 공식 문서에서도 관련 내용을 확인할 수 있다.

https://django-rest-auth.readthedocs.io/en/latest/configuration.html

 

Configuration — django-rest-auth 0.9.5 documentation

Note The custom REGISTER_SERIALIZER must define a def save(self, request) method that returns a user model instance

django-rest-auth.readthedocs.io

from .models import User
from rest_framework import serializers
from django.core.exceptions import ValidationError as DjangoValidationError
from allauth.account.adapter import get_adapter


class SignUpSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['email', 'password', 'realname', 'nickname', 'address', 'phone', 'height', 'weight']

    def get_cleaned_data(self):
        return {
            'realname': self.validated_data.get('realname', ''),
            'password': self.validated_data.get('password', ''),
            'email': self.validated_data.get('email', ''),
            'nickname': self.validated_data.get('nickname', ''),
            'address': self.validated_data.get('address', ''),
            'phone': self.validated_data.get('phone', ''),
            'height': self.validated_data.get('height', ''),
            'weight': self.validated_data.get('weight', ''),
        }

    def save(self, request):
        adapter = get_adapter()
        user = adapter.new_user(request)
        self.cleaned_data = self.get_cleaned_data()
        user = adapter.save_user(request, user, self, commit=False)
        if "password" in self.cleaned_data:
            try:
                adapter.clean_password(self.cleaned_data['password'], user=user)
            except DjangoValidationError as exc:
                raise serializers.ValidationError(
                    detail=serializers.as_serializer_error(exc)
                )
        user.save()
        return user

다음은 adapters.py인데 adapter는 allauth의 클래스이다.

자세한 내용은 공식문서에서 확인할 수 있다.

https://django-allauth.readthedocs.io/en/latest/installation.html

 

Installation — django-allauth 0.43.0 documentation

Post-Installation In your Django root execute the command below to create your database tables: Now start your server, visit your admin pages (e.g. http://localhost:8000/admin/) and follow these steps: Add a Site for your domain, matching settings.SITE_ID

django-allauth.readthedocs.io

from allauth.account.adapter import DefaultAccountAdapter


class CustomAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        data = form.cleaned_data
        # 기본 저장 필드: username, email
        user = super().save_user(request, user, form, False)
        # 추가 저장 필드: realname, nickname, address, phone, height, weight
        realname = data.get('realname')
        nickname = data.get('nickname')
        address = data.get('nickname')
        phone = data.get('phone')
        height = data.get('height')
        weight = data.get('weight')
        if realname:
            user.realname = realname
        if nickname:
            user.nickname = nickname
        if address:
            user.address = address
        if phone:
            user.phone = phone
        if height:
            user.height = height
        if weight:
            user.weight = weight
        user.save()
        return user

그리고 settings.py 에서도 관련된 설정들을 해줘야 한다.

AUTH_USER_MODEL = 'accounts.User'

REST_AUTH_REGISTER_SERIALIZERS = {
    'REGISTER_SERIALIZER': 'accounts.serializers.SignUpSerializer'
}

ACCOUNT_ADAPTER = 'accounts.adapters.CustomAccountAdapter'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
    ],
}

이렇게 해서 dj-rest-auth와 allauth를 사용한 회원가입기능을 구현해봤다.