224

I've tried something like this, it does not work.

class PostSerializer(serializers.ModelSerializer):
 class Meta:
 model = Post
 def save(self):
 user = self.context['request.user']
 title = self.validated_data['title']
 article = self.validated_data['article']

I need a way of being able to access request.user from my Serializer class.

Yevgeniy Shchemelev
3,6612 gold badges34 silver badges40 bronze badges
asked May 13, 2015 at 0:28
1

15 Answers 15

385

You cannot access the request.user directly. You need to access the request object, and then fetch the user attribute.

Like this:

user = self.context['request'].user

Or to be more safe,

user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
 user = request.user

More on extra context can be read here

answered May 13, 2015 at 1:06
Sign up to request clarification or add additional context in comments.

7 Comments

it says NameError: name 'self' is not defined
of course, this was in the context of a class. You are most likely not in the context of a class
In my serializer, in validate() method, self.context is an empty dict. Why?
David - you probably solved this long ago, but if anyone else has this issue, it could be because you are constructing your serializer manually. I had this problem in a nested serializer instantiated for a generic relationship. The docs say to do serializer = NoteSerializer(value) but this will only pass your instance, not the context containing the request. You can pass kwargs to the constructor and send it the info it needs (see get_serializer or GenericAPIView for how it does it)
@JonVaughan any detail how to pass kwargs to the serializer instance??
|
89

Actually, you don't have to bother with context. There is a much better way to do it:

from rest_framework.fields import CurrentUserDefault
class PostSerializer(serializers.ModelSerializer):
 class Meta:
 model = Post
 def save(self):
 user = CurrentUserDefault() # <= magic!
 title = self.validated_data['title']
 article = self.validated_data['article']
answered Jan 24, 2016 at 11:41

3 Comments

It did not work,its returning a Null object. user_edit = serializers.CurrentUserDefault()
@EndersonMenezes It's probably best worked with the IsAuthenticated permission.
Not fully related, but interesting: I have readwrite PrimaryKeyRelatedField and I need to filter possibilities (which are users addresses) for current user only. I made derrived class MyAddresses(PrimaryKeyRelatedField) and I try rewrite get_queryset() there using .filter(user=..). I have problem to get request.user there. Additionally I have no success with user=CurrentUserDefault(). However I have success and can access the user by calling it: CurrentUserDefault()(self) makes the trick. [self relates to the MyAddresses class/object]
61

As Igor mentioned in other answer, you can use CurrentUserDefault. If you do not want to override save method just for this, then use doc:

from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
 user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
 class Meta:
 model = Post
haccks
107k28 gold badges181 silver badges274 bronze badges
answered May 4, 2016 at 9:00

3 Comments

doc link is now mislinked.
Link to the official DRF documentation with this same example django-rest-framework.org/api-guide/serializers/…
I used HiddenField instead of PrimaryKeyRelatedField without read read_only attiribute, it works. As I understood there is no security problem.
19

Use this code in view:

serializer = UploadFilesSerializer(data=request.data, context={'request': request})

then access it with this in serializer:

user = self.context.get("request").user
answered Feb 21, 2021 at 7:52

Comments

12

CurrentUserDefault A default class that can be used to represent the current user. In order to use this, the 'request' must have been provided as part of the context dictionary when instantiating the serializer.

in views.py

serializer = UploadFilesSerializer(data=request.data, context={'request': request})

This is example to pass request

in serializers.py

owner = serializers.HiddenField(
 default=serializers.CurrentUserDefault()
)

Source From Rest Framework

answered Jan 5, 2021 at 13:47

Comments

11

For those who used Django's ORM and added the user as a foreign key, they will need to include the user's entire object, and I was only able to do this in the create method and removing the mandatory field:

class PostSerializer(serializers.ModelSerializer):
def create(self, validated_data):
 
 request = self.context.get("request")
 
 post = Post()
 post.title = validated_data['title']
 post.article = validated_data['article']
 post.user = request.user
 post.save()
 return post
class Meta:
 model = Post
 fields = '__all__'
 extra_kwargs = {'user': {'required': False}}
answered Nov 24, 2020 at 17:01

1 Comment

request = self.context.get("request") is what I was looking for!
7

You can pass request.user when calling .save(...) inside a view:

class EventSerializer(serializers.ModelSerializer):
 class Meta:
 model = models.Event
 exclude = ['user']
class EventView(APIView):
 def post(self, request):
 es = EventSerializer(data=request.data)
 if es.is_valid():
 es.save(user=self.request.user)
 return Response(status=status.HTTP_201_CREATED)
 return Response(data=es.errors, status=status.HTTP_400_BAD_REQUEST)

This is the model:

class Event(models.Model):
 user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
 date = models.DateTimeField(default=timezone.now)
 place = models.CharField(max_length=255)
answered Nov 8, 2019 at 22:46

1 Comment

The exclude = ['user'] did the job for me. I had declared it as write_only = True but with your solution is not needed anymore. Much more clear than defining it as read_only = True
6

In GET method:

Add context={'user': request.user} in the View class:

class ContentView(generics.ListAPIView):
 def get(self, request, format=None):
 content_list = <Respective-Model>.objects.all()
 serializer = ContentSerializer(content_list, many=True, 
 context={'user': request.user})

Get it in the Serializer class method:

class ContentSerializer(serializers.ModelSerializer):
 rate = serializers.SerializerMethodField()
 def get_rate(self, instance):
 user = self.context.get("user") 
 ... 
 ...

In POST method:

Follow other answers (e.g. Max's answer).

answered Apr 23, 2022 at 18:52

Comments

4

You need a small edit in your serializer:

class PostSerializer(serializers.ModelSerializer):
 class Meta:
 model = Post
 def save(self):
 user = self.context['request'].user
 title = self.validated_data['title']
 article = self.validated_data['article']

Here is an example, using Model mixing viewsets. In create method you can find the proper way of calling the serializer. get_serializer method fills the context dictionary properly. If you need to use a different serializer then defined on the viewset, see the update method on how to initiate the serializer with context dictionary, which also passes the request object to serializer.

class SignupViewSet(mixins.UpdateModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
 http_method_names = ["put", "post"]
 serializer_class = PostSerializer
 def create(self, request, *args, **kwargs):
 serializer = self.get_serializer(data=request.data)
 serializer.is_valid(raise_exception=True)
 self.perform_create(serializer)
 headers = self.get_success_headers(serializer.data)
 return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
 def update(self, request, *args, **kwargs):
 partial = kwargs.pop('partial', False)
 instance = self.get_object()
 kwargs['context'] = self.get_serializer_context()
 serializer = PostSerializer(instance, data=request.data, partial=partial, **kwargs)
 serializer.is_valid(raise_exception=True)
 self.perform_update(serializer) 
 return Response(serializer.data)
answered Jul 19, 2019 at 11:02

Comments

4

You can not access self.context.user directly. First you have to pass the context inside you serializer. For this follow steps bellow:

  1. Some where inside your api view:

     class ApiView(views.APIView):
     def get(self, request):
     items = Item.object.all()
     return Response(
     ItemSerializer(
     items, 
     many=True,
     context=request # <- this line (pass the request as context)
     ).data
     )
    
  2. Then inside your serializer:

     class ItemSerializer(serializers.ModelSerializer):
     current_user = serializers.SerializerMethodField('get_user')
     class Meta:
     model = Item
     fields = (
     'id',
     'name',
     'current_user',
     )
     def get_user(self, obj):
     request = self.context
     return request.user # <- here is current your user 
    
answered Mar 27, 2021 at 22:53

Comments

3

The solution can be simple for this however I tried accessing using self.contenxt['request'].user but not working in the serializer.

If you're using DRF obviously login via token is the only source or maybe others that's debatable.

Moving toward a solution.

Pass the request.user instance while creating serializer.create

views.py

if serializer.is_valid():
 watch = serializer.create(serializer.data, request.user)

serializer.py

 def create(self, validated_data, usr):
 return Watch.objects.create(user=usr, movie=movie_obj, action=validated_data['action'])
answered Aug 22, 2020 at 5:21

Comments

2

The best way to get current user inside serializer is like this.

AnySerializer(data={
 'example_id': id
 }, context={'request': request})

This has to be written in views.py And now in Serializer.py part

user = serializers.CharField(default=serializers.CurrentUserDefault())

This "user" must be your field in Model as any relation like foreign key

answered Jan 6, 2023 at 6:07

Comments

1

If you are using generic views and you want to inject current user at the point of saving the instance then you can override perform_create or perform_update:

def perform_create(self, serializer):
 serializer.save(user=self.request.user)

user will be added as an attribute to kwargs and you can access it through validated_data in serializer

user = validated_data['user']
answered Nov 10, 2020 at 19:04

Comments

0

drf srz page

in my project it worked my user field was read only so i needed to get user id in the create method

class CommentSerializer(serializers.ModelSerializer):
 comment_replis = RecursiveField(many=True, read_only=True)
 user = UserSerializer(read_only=True)
 class Meta:
 model = PostComment
 fields = ('_all_')
 def create(self, validated_data):
 
 post = PostComment.objects.create(**validated_data) 
 print(self._dict_['_kwargs']['data']["user"]) # geting #request.data["user"] # <- mian code
 post.user=User.objects.get(id=self._dict_['_kwargs']['data']["user"])
 return post

in my project i tried this way and it work

answered Feb 9, 2022 at 19:30

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
You need to call post.save() after you called post.user=..., else the relation wont be stored in the database.
0

as others answered, should use self.context['request'].user , but consider it does not work with GenericAPIView , should use ListAPIView or RetrieveAPIView

while GenericAPIView does not send request context to serializer

answered May 28, 2023 at 4:03

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.