LearnToday
LearnToday

Reputation: 2902

Api Post always has user as null even though there is a logged in user

I am trying to have an api for my answers app. When a post is created, the user is always set to null. I am not sure of why that is.

How do I auto-add some fields to the saving object, like the authenticated user, user IP address?

Here is my serializer:

User = get_user_model()

class UserPublicSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'username',
            'first_name',
            'last_name',
            'is_staff',
            'photo_url'
        ]
class AnswerCreateUpdateSerializer(ModelSerializer):
    user = UserPublicSerializer(read_only=True)
    class Meta:
        model = Answer
        fields = [
            'object_pk',
            'content_type',
            'answer',
            'user'
        ]
        read_only_fields = ['user']

And the api create view:

class AnswerCreateAPIView(CreateAPIView):
    queryset = Answer.objects.all()
    serializer_class = AnswerCreateUpdateSerializer

And the model is:

class AnswerAbstractModel(BaseAnswerAbstractModel):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'),
                             blank=True, null=True, related_name="%(class)s_answers",
                             on_delete=models.SET_NULL)
    answer = FroalaField()
    submit_date = models.DateTimeField(_('date/time submitted'), default=None, db_index=True)
    ip_address = models.GenericIPAddressField(_('IP address'), unpack_ipv4=True, blank=True, null=True)


class Answer(AnswerAbstractModel):
    class Meta(AnswerAbstractModel.Meta):
        db_table = "answers"

I beg your pardon for my ignorance of the django world. I am trying hard to figure it out though.

That said, what should be the approach here?

Upvotes: 0

Views: 70

Answers (1)

JPG
JPG

Reputation: 88659

You have to override the perform_create() method of the AnswerCreateAPIView as below,

class AnswerCreateAPIView(CreateAPIView):
    queryset = Answer.objects.all()
    serializer_class = AnswerCreateUpdateSerializer

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

Update-1

Why do you need to override?

Case-1

You set user as read_only_field in your AnswerCreateUpdateSerializer. By doing so DRF serialzier won't fetch any input data from JSON payload even if the data present in it

Case-2

If you unset the read_only property, DRF will ask you to provide a dict like object for the user since you have a Nested serializer configuration.

The DRF way

If you want to save the logged-in user to the DB in DRF, you should set the user field as read_only and override appropriate methods and fetch the logged-in user from request object.

Upvotes: 1

Related Questions