Django REST Framework - User 생성 & 사용자 권한 관리

2025. 3. 10.·학습 주제/Django & Django Rest Framework
 

Form과 Serializer를 사용하여 User 생성하기

 

Form을 사용하여 User 생성하기

Django가 제공하는 UserCreationForm을 활용하면 기본적인 회원가입 기능을 간단하게 구현할 수 있다.

View 작성

  • generic.CreateView를 사용하여 새로운 유저를 생성한다.
  • UserCreationForm을 활용하면 기본적인 사용자 생성 폼을 제공받을 수 있다.
  • 회원가입이 완료되면 reverse_lazy('user-list')를 통해 특정 URL로 이동한다.
# polls/views.py
from django.views import generic
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm

class SignupView(generic.CreateView):
    form_class = UserCreationForm
    success_url = reverse_lazy('user-list')
    template_name = 'registration/signup.html'

Template 작성

  • Django의 form.as_p를 사용하여 폼을 HTML로 변환하여 출력한다.
  • CSRF 보안을 위해 {% csrf_token %}을 추가한다.
<!-- templates/registration/signup.html -->
<h2>회원가입</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">가입하기</button>
</form>

URL 연결

  • SignupView를 /signup/ URL에 연결한다.
# polls/urls.py
from django.urls import path
from .views import SignupView

urlpatterns = [
    path('signup/', SignupView.as_view(), name='signup'),
]

reverse_lazy 확인하기

  • reverse_lazy는 URL을 지연 평가(lazy evaluation)하여 사용할 수 있도록 해준다.
# Django shell에서 확인
from django.urls import reverse_lazy
reverse_lazy('user-list')

Serializer를 사용하여 User 생성하기

Django REST framework(DRF)를 사용하면 Serializer를 통해 API 기반으로 사용자 등록 기능을 만들 수 있다.

Serializer 작성

  • ModelSerializer를 활용하여 User 모델 기반의 RegisterSerializer를 생성한다.
  • extra_kwargs = {'password': {'write_only': True}}을 추가하여 비밀번호가 응답에 포함되지 않도록 설정한다.
# polls_api/serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers

class RegisterSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

View 작성

  • CreateAPIView를 사용하여 새로운 사용자 등록 API를 생성한다.
  • serializer_class에 RegisterSerializer를 연결한다.
# polls_api/views.py
from rest_framework import generics
from polls_api.serializers import RegisterSerializer

class RegisterUser(generics.CreateAPIView):
    serializer_class = RegisterSerializer

비밀번호 검증 및 추가 기능

Django의 User 모델에는 비밀번호 검증 기능이 포함되어 있지 않아 보완하기 위한 기능 추가

간단한 비밀번호 검증 추가

  • validate_password를 사용하여 Django의 기본 비밀번호 검증 정책을 적용한다.
# polls_api/serializers.py
from django.contrib.auth.password_validation import validate_password

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])

비밀번호 확인 기능 추가

  • password2 필드를 추가하여 비밀번호 확인 기능을 제공한다.
  • validate 메서드를 오버라이딩하여 두 개의 비밀번호가 일치하는지 검사한다.
# polls_api/serializers.py
class RegisterSerializer(serializers.ModelSerializer):
    password2 = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = User
        fields = ['username', 'password', 'password2']

    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError({"password": "두 개의 비밀번호가 일치하지 않습니다."})
        return attrs

비밀번호 암호화 저장

  • set_password() 메서드를 사용하여 비밀번호를 암호화한 후 저장한다.
# polls_api/serializers.py
    def create(self, validated_data):
        user = User.objects.create(username=validated_data['username'])
        user.set_password(validated_data['password'])  # 비밀번호 암호화
        user.save()
        return user

 

사용자 권한 관리

 

DRF에서 로그인/로그아웃 버튼 추가하기

  • Django REST Framework는 기본적으로 api-auth/ 엔드포인트를 제공
  • 이를 추가하면 로그인 및 로그아웃 버튼이 자동으로 표시된다.
# polls_api/urls.py
path('api-auth/', include('rest_framework.urls')),

# mysite/settings.py
from django.urls import reverse_lazy
LOGIN_REDIRECT_URL = reverse_lazy('question-list')
LOGOUT_REDIRECT_URL = reverse_lazy('question-list')

질문을 생성한 사용자를 자동으로 owner로 설정하기

질문을 생성한 사용자를 owner 필드에 자동으로 할당하려면 perform_create 메서드를 오버라이드해야 함

Serializer에서 owner 필드 추가하기

  • owner 필드를 ReadOnlyField로 설정하면 클라이언트가 직접 값을 입력하지 못함
    • 서버에서 자동으로 할당할 수 있습니다.
# polls_api/serializers.py
from rest_framework import serializers
from .models import Question

class QuestionSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    
    class Meta:
        model = Question
        fields = ['id', 'question_text', 'owner']

perform_create에서 owner 자동 지정하기

# polls_api/views.py
from rest_framework import generics
from .models import Question
from .serializers import QuestionSerializer

class QuestionList(generics.ListCreateAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

로그아웃 상태에서 질문을 생성할 경우 에러 방지하기

  • 로그아웃 상태에서는 질문을 생성하지 못하도록, IsAuthenticatedOrReadOnly 권한을 추가
# polls_api/views.py
from rest_framework import permissions

class QuestionList(generics.ListCreateAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
  • 같은 권한을 QuestionDetail에도 추가하여, 로그인하지 않은 사용자는 읽기만 가능하도록 설정
class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

본인 질문만 수정할 수 있도록 권한 설정하기

IsOwnerOrReadOnly 권한 클래스 생성

# polls_api/permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # 읽기 권한은 누구에게나 허용
        if request.method in permissions.SAFE_METHODS:
            return True
        
        # 수정 및 삭제 권한은 owner만 가능
        return obj.owner == request.user

QuestionDetail에 권한 적용

# polls_api/views.py
from .permissions import IsOwnerOrReadOnly

class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]

Perform_create() 동작 원리 이해하기

  • perform_create()는 CreateModelMixin에서 정의된 create() 메서드에서 호출됩니다.
  • 기본적으로 serializer.save()를 호출하며, 이를 오버라이드하여 추가 로직을 삽입할 수 있습니다.
# QuestionList 내부 동작
class QuestionList(generics.ListCreateAPIView):
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

serializer.save() 동작 방식

  • serializer.save()는 validated_data를 기반으로 객체를 저장
  • ReadOnlyField로 설정된 필드는 직접 입력되지 않지만 save()에서 추가하면 반영됩니다.
django shell
from polls_api.serializers import QuestionSerializer

# 데이터 입력
question_serializer = QuestionSerializer(data={"question_text": "some_text", "owner": "someone"})
question_serializer.is_valid()

# owner 필드는 ReadOnlyField이므로 제외됨
print(question_serializer.validated_data)
# Output: OrderedDict([('question_text', 'some_text')])

# save() 호출 시 owner를 지정하면 저장 가능
question = question_serializer.save(owner=request.user)
print(question.owner)  # 현재 로그인한 사용자

'학습 주제 > Django & Django Rest Framework' 카테고리의 다른 글

Django REST Framework - Votes  (0) 2025.03.10
Django REST Framework - Postman & RelatedFiled  (0) 2025.03.10
Django REST Framework - Views  (0) 2025.03.10
Django REST Framework - Serializer & API  (0) 2025.03.10
Django - 예외 처리하기 & Admin  (0) 2025.03.10
'학습 주제/Django & Django Rest Framework' 카테고리의 다른 글
  • Django REST Framework - Votes
  • Django REST Framework - Postman & RelatedFiled
  • Django REST Framework - Views
  • Django REST Framework - Serializer & API
굥여9
굥여9
9idryd 님의 블로그 입니다.
  • 굥여9
    문과의 개발
    굥여9
  • 전체
    오늘
    어제
    • 분류 전체보기 (114)
      • 학습 주제 (86)
        • 자료구조와 알고리즘 (8)
        • HTML & 웹크롤링 (4)
        • 데이터 시각화 (4)
        • Django & Django Rest Framew.. (11)
        • AWS 클라우드 (6)
        • SQL & 데이터 웨어하우스 (11)
        • 데이터파이프라인과 Airflow (12)
        • Docker & K8S (8)
        • DBT (4)
        • CI & CD (1)
        • 빅데이터 처리와 Spark (12)
        • Kafka & Spark Streaming (5)
        • 보안 엔지니어링 (0)
      • 구름 프로펙트 클라우드 엔지니어링 (0)
        • [Monolithic] 서비스의 기초와 설계 (0)
        • [MSA & EDA] 비동기 전환과 정합성 (0)
        • [Cloud Native] K8s 기반 인프라와 .. (0)
      • 프로그래머스 데브코스 데이터 엔지니어링 (4)
      • 개발 기록 (24)
        • 일일 (24)
        • 주간 (0)
      • 회고 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
굥여9
Django REST Framework - User 생성 & 사용자 권한 관리
상단으로

티스토리툴바