0

I am trying to create an API but the serializer is failing . I am not able to figure out what has gone wrong .

View :

elif request.method == 'POST':
    data = { 'user':request.data.get('user'),'skill_item':request.data.get('new_user_skill')}
    serializer = UserSkillSerializer(data=data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)  

Serializer :

    class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email')
        extra_kwargs = {
            'username': {
                'validators': [UnicodeUsernameValidator()],
            }
        }    


class UserProfileSerializer(serializers.ModelSerializer):
    skill_item =SkillSerializer(read_only=True,many=True) 
    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email','skill_item')
        extra_kwargs = {
            'username': {
                'validators': [UnicodeUsernameValidator()],
            }
        }   

        def create(self, validated_data):

            user = UserModelSerializer.create(UserModelSerializer(),username=validated_data.get('username'))
            user.save()

            UserProfile.objects.create(user=user, user_skills=skill_item)
            return user

class UserSkillSerializer(serializers.ModelSerializer):
    user = UserProfileSerializer(required=True)
    skill_item = SkillSerializer(required=True)
    class Meta:
        model = UserSkill
        fields= '__all__'

    def create (Self,validated_data):
        user_data = validated_data.pop('user')
        user = UserProfileSerializer.create(UserProfileSerializer(),validated_data=user_data)
        skill_data = validated_data.pop('skill_item')
        skill = SkillSerializer.create(SkillSerializer(),validated_data=skill_data)
        user_skill, created = UserSkill.objects.update_or_create(user=user,skill_item=skill_item)

        return user_skill
class SkillSerializer(serializers.ModelSerializer):

    class Meta:
        model = Skill
        fields = '__all__'
        extra_kwargs = {
            'skill_name': {
                'validators': [UnicodeUsernameValidator()],
            }
        } 

Model :

# This class will more or less map to a table in the database and defines skills at the application level
class Skill (models.Model):
    # this defines a required name that cannot be more than 100 characters.
    skill_name = models.CharField(max_length=100,unique=True)
    class Meta:
        app_label = "wantedly_webapp"

# This class will more or less map to a table in the database and defines the many to many relationship between user-skill, this is our intermediate model
class UserSkill(models.Model):
    """ A Model for representing skill in user profile """
    unique_together = (('user', 'skill_item'),)

    user = models.ForeignKey('UserProfile',on_delete=models.CASCADE,related_name='current_user_skills')

    skill_item = models.ForeignKey(Skill,on_delete=models.CASCADE)

    def __str__(self):
        """Return a human readable representation of the model instance."""
        return "{}".format(self.skill_item.skill_name)

# this class adds a Many to Many field in existing django-rest auth UserProfile class for  user and his/her skills 
class UserProfile(models.Model):
    user = models.OneToOneField('auth.User',unique=True,on_delete=models.CASCADE,related_name='user_profile')
    user_skills = models.ManyToManyField(
            Skill,
            through='UserSkill',
            through_fields=('user','skill_item')
        )

The error which I am getting is basically happening because of my bad request to the view , which failes on

serialzer.is_valid()

I am not sure why my UserProfileSerialzer is not able to serialze correctly .

Edit 1

I am facing following errors now :

    {
        "user": {
            "non_field_errors": [
                "Invalid data. Expected a dictionary, but got User."
            ]
        },
        "skill_item": {
            "non_field_errors": [
                "Invalid data. Expected a dictionary, but got Skill."
            ]
        }

}

I believe this is happening because my Serializer are not able to handle the Nested relations of foreign key and many to many relations .

Edit 2 - I am facing following errors now -

 File "C:\code\django\wantedly\src\wantedly_webapp\serializers\UserSkillSerializer.py", line 49, in create
   user = UserProfileSerializer.create(UserProfileSerializer(),validated_data=user_data)

IntegrityError at /api/v1/user/skills/ UNIQUE constraint failed: auth_user.username

Divyanshu Jimmy
  • 2,542
  • 5
  • 32
  • 48

1 Answers1

1

I believe your problem is not on the serializer.is_valid() line, but on the one trying to render errors below:

return Response({serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

This will fail because serializer.errors is a ReturnDict and you are trying to make a set of it using the {} syntax. Use instead:

return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
dukebody
  • 7,025
  • 3
  • 36
  • 61
  • please checked Edit-1 in question , i guess my serializer are not correct . Can you please check it for my models and serializer for same view.Removing casting from dict to set worked like a charm ! – Divyanshu Jimmy Jan 21 '18 at 02:27
  • The error you mention on "Edit 1" happens because you are passing Django objects as data to the serializer, while the serializer expects dicts with the defined schemas instead. `data = { user':request.data.get('user'),'skill_item':request.data.get('new_user_skill')}` is the line to blame. – dukebody Jan 21 '18 at 08:48
  • Regarding the second error, that's because your `UserProfileSerializer` tries to create a new user and an user with that username already exists. You probably want to guard for that in your view and return 400 if an existing user with the given username already exists. BTW for new issues please open new questions, otherwise it's pretty hard to give a definitive answer to anything. :) – dukebody Jan 21 '18 at 08:51
  • please check updated query here https://stackoverflow.com/questions/48365600/django-serializer-unable-to-pass-correct-data-in-many-to-many-relation-with-ne – Divyanshu Jimmy Jan 21 '18 at 09:55