Django-Rest-Framework Serializer에서 Request.User를 가져오는 방법
Django-Rest-Framework Serializer에서 Request.User를 가져오는 방법
context 속성 사용:
Serializer의 context
속성에는 현재 요청과 관련된 정보가 포함됩니다. 여기에는 request
객체도 포함되어 있으며, 이를 통해 request.user
속성에 접근하여 현재 로그인한 유저 정보를 얻을 수 있습니다.
from django.contrib.auth.models import User
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
def to_representation(self, instance):
data = super().to_representation(instance)
user = self.context['request'].user
data['user_id'] = user.id
return data
get_serializer_context 메소드 오버라이드:
Serializer 클래스에서 get_serializer_context
메소드를 오버라이드하여 현재 요청 객체를 context 속성에 추가할 수 있습니다.
from django.contrib.auth.models import User
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
def get_serializer_context(self):
context = super().get_serializer_context()
context['request'] = self.context['request']
return context
def to_representation(self, instance):
data = super().to_representation(instance)
user = self.context['request'].user
data['user_id'] = user.id
return data
CurrentUserDefault 필드 사용:
Django-Rest-Framework에서 제공하는 CurrentUserDefault
필드를 사용하여 Serializer에서 현재 유저 정보를 자동으로 가져올 수 있습니다.
from django.contrib.auth.models import User
from rest_framework.serializers import CurrentUserDefault
class MySerializer(serializers.ModelSerializer):
user = CurrentUserDefault()
class Meta:
model = MyModel
직접 request 객체를 가져오기:
Serializer 클래스에서 직접 request
객체를 가져와 request.user
속성에 접근하여 현재 로그인한 유저 정보를 얻을 수 있습니다.
from django.contrib.auth.models import User
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
def to_representation(self, instance):
data = super().to_representation(instance)
request = self.context['view'].request
user = request.user
data['user_id'] = user.id
return data
예제 코드
from django.contrib.auth.models import User
from rest_framework import serializers
class MyModel(models.Model):
name = models.CharField(max_length=255)
class MySerializer(serializers.ModelSerializer):
# 1. `context` 속성 사용
# user_id = serializers.SerializerMethodField()
# 2. `get_serializer_context` 메소드 오버라이드
# user_id = serializers.SerializerMethodField()
# 3. `CurrentUserDefault` 필드 사용
user = CurrentUserDefault()
# 4. 직접 `request` 객체 가져오기
# user_id = serializers.SerializerMethodField()
class Meta:
model = MyModel
fields = ('id', 'name', 'user')
# 1. `context` 속성 사용
# def get_user_id(self, obj):
# return self.context['request'].user.id
# 2. `get_serializer_context` 메소드 오버라이드
# def get_serializer_context(self):
# context = super().get_serializer_context()
# context['request'] = self.context['request']
# return context
# 4. 직접 `request` 객체 가져오기
# def get_user_id(self, obj):
# request = self.context['view'].request
# return request.user.id
- 위 코드는 예시이며, 상황에 맞게 수정해야 합니다.
user_id
필드 이름은 원하는 대로 변경할 수 있습니다.
Django-Rest-Framework Serializer에서 Request.User를 가져오는 대체 방법
Serializer mixin 사용:
Serializer mixin을 사용하여 Serializer 클래스에 get_user
메소드를 추가할 수 있습니다.
from django.contrib.auth.models import User
from rest_framework import serializers
class MySerializerMixin(object):
def get_user(self):
return self.context['request'].user
class MySerializer(MySerializerMixin, serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'name', 'user')
Custom viewset 사용:
from django.contrib.auth.models import User
from rest_framework import viewsets, serializers
class MyModelViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def get_serializer_context(self):
context = super().get_serializer_context()
context['user'] = self.request.user
return context
class MySerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
class Meta:
model = MyModel
fields = ('id', 'name', 'user')
Thread local storage 사용:
Thread local storage를 사용하여 현재 요청과 관련된 유저 정보를 저장하고 Serializer에서 접근할 수 있습니다.
from django.contrib.auth.models import User
from rest_framework import serializers
from threading import local
_user_storage = local()
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'name', 'user')
def to_representation(self, instance):
data = super().to_representation(instance)
data['user_id'] = _user_storage.user.id
return data
def get_current_user():
return _user_storage.user
def set_current_user(user):
_user_storage.user = user
@csrf_exempt
def my_view(request):
set_current_user(request.user)
serializer = MySerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
Django signals 사용:
from django.contrib.auth.models import User
from django.dispatch import receiver
from rest_framework import serializers
@receiver(user_logged_in)
def on_user_logged_in(sender, user, request, **kwargs):
request._user = user
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'name', 'user')
def to_representation(self, instance):
data = super().to_representation(instance)
data['user_id'] = self.context['request']._user.id
return data
@csrf_exempt
def my_view(request):
serializer = MySerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
주의:
- 위 방법들은 상황에 따라 유용할 수 있지만, 주의해서 사용해야 합니다.
- Thread local storage와 Django signals는 여러 요청에서 동시에 사용될 경우 문제가 발생할 수 있습니다.
django django-rest-framework