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 |