Populate readonly nested serializer

Question:

I’m using ModelViewSets and I have nested serializer for these models.

class Profile(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    place = models.OneToOneField(Place, on_delete=models.DO_NOTHING)
    bio = models.TextField(null=True)

class User(AbstractBaseUser, PermissionsMixin):
    
    id          = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email       = models.EmailField(_('email address'), unique=True)
    first_name  = models.CharField(max_length=150, blank=True)
    is_staff    = models.BooleanField(default=False)
    is_active   = models.BooleanField(default=False)

    objects = CustomAccountManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']

    def __str__(self):
        return self.email

update
How can I autocomplete a newly created profile with 1:1 relation to User that is sending the request?

So, you are registering on a website, now you are a user but you want to have profile, some bio so you are setting up your profile for that

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        exclude = ('password', 'is_superuser', 'is_staff', 'groups', 'user_permissions')

class ProfileSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):

    user = UserSerializer(read_only=True)
    place = PlaceSerializer(read_only=True)

    class Meta:
        model = Profile
        fields = '__all__'
        depth = 1

viewsets

class ProfileViewSet(viewsets.ModelViewSet):
    serializer_class = ProfileSerializer
    get_queryset = Profile.objects.all()

    def create(self, request):
        serializer = ProfileSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            data = serializer.data
            return Response(data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

As you can see I’m using ‘drf-writable-nested’ and it works okay but I can’t figure it out how to automatically connect profile to user on new profile creation.

Asked By: rafaelHTML

||

Answers:

You will have CurrentUserDefault if you want to use read_only field.

user = serializers.PrimaryKeyRelatedField(
    read_only=True, 
    default=serializers.CurrentUserDefault()
)

Or you can omit user and pass it while saving the serializer like this:
serializer.save(user=request.user)

Answered By: haox_illued

To automatically connect a newly created profile to the user sending the request, you can modify the create method in your ProfileViewSet. Here’s one way to do it:

class ProfileViewSet(viewsets.ModelViewSet):
    serializer_class = ProfileSerializer
    queryset = Profile.objects.all()

    def create(self, request):
        serializer = ProfileSerializer(data=request.data)
        if serializer.is_valid():
            # Set the user to the requesting user
            serializer.save(user=request.user)
            data = serializer.data
            return Response(data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Note that this assumes that you are using token authentication or some other form of authentication that identifies the user making the request. If not, you will need to modify this code accordingly to identify the user in some other way.

Answered By: Sunderam Dubey