Home > Mobile >  How to post manytomany field value in Postman for API
How to post manytomany field value in Postman for API

Time:12-16

I have a field which is ManyToMany. I would like to enter the value in POSTMAN for API post operation. But everytime It says: "This field is required." even though I provided the value. enter image description here

enter image description here

Models:

class Day(models.Model):
   day_name = models.CharField(
      _("Day Name"), max_length=255, null=True, blank=True)

   def __str__(self):
       return self.day_name

class TutorProfile(models.Model):

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    tutor_availablility = models.ManyToManyField(
         Day,blank=True)

Serializer:

class DaySerializer(serializers.ModelSerializer):

class Meta:
    model = Day 
    fields = '__all__'
    


class TutorProfileSerializer(serializers.ModelSerializer):

    user = serializers.PrimaryKeyRelatedField(
        read_only=True, default=serializers.CurrentUserDefault(), source='user.username')
    image_url = serializers.SerializerMethodField('get_image_url')
    
    tutor_availablility = DaySerializer(many=True)

    class Meta:
        model = TutorProfile
        fields = '__all__'

Viewsets:

@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
class TutorprofileViewSet(ModelViewSet):
    serializer_class = TutorProfileSerializer
    http_method_names = ["post", "delete", "get"]
    queryset = TutorProfile.objects.all()

CodePudding user response:

With the following models.py (notice that your current Day.__str__ can raise an exception if day_name does not exist):


class Day(models.Model):
    day_name = models.CharField(_("Day Name"), max_length=255, blank=True, null=True)

    def __str__(self):
        return self.day_name if self.day_name else "Unnamed"


class TutorProfile(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    tutor_availability = models.ManyToManyField(Day, blank=True)

You do not need to explicitly add tutor_availability nor user as serializer fields:

class DaySerializer(serializers.ModelSerializer):
    class Meta:
        model = Day
        fields = "__all__"


class TutorProfileSerializer(serializers.ModelSerializer):
    # Omitting `image_url` as not reflected in `models.py`
    # image_url = serializers.SerializerMethodField('get_image_url')
    
    class Meta:
        model = TutorProfile
        fields = "__all__"

With this viewset:

@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
class TutorProfileViewSet(ModelViewSet):
    serializer_class = TutorProfileSerializer
    http_method_names = ["post", "delete", "get"]
    queryset = TutorProfile.objects.all()

Then, after creating days with IDs 1 and 2 in admin, by sending the tutor_availability field as you are doing it, it should work. Request:

{
    "user": 1,
    "tutor_availability": [1, 2]
}

Response:

{
    "id": 1,
    "user": 1,
    "tutor_availability": [
        1,
        2
    ]
}

Notice as well that I've changed availablility to availability and that it may be unsafe to allow authenticated users to pass the user field in the request, you may want to infer that from the user who makes the request.

CodePudding user response:

In your TutorProfileSerializer you are using the DaySerializer for tutor_availablility field so when you do a post request your post action will wait for a list of dict, what you you need to do in first is to delete this line : from your TutorProfileSerializer and it will works.

tutor_availablility = DaySerializer(many=True)

If you still have the problem then you need to verify the validate method of the TutorProfileSerializer.

And if it works but you want a list of dict(of Day object) for GET request, you need to override the get_serializer_class() of your ViewSet and create two serializers one for post request and a second for get request:

@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
class TutorprofileViewSet(ModelViewSet):
    serializer_class = TutorProfileSerializer
    http_method_names = ["post", "delete", "get"]
    queryset = TutorProfile.objects.all()

    def get_serializer_class(self):
        if self.action.method == 'GET':
            return TutorGETProfileSerializer
        return super(TutorprofileViewSet, self).get_serializer_class()

and the 2 serializers:

class TutorGETProfileSerializer(serializers.ModelSerializer):

    user = serializers.PrimaryKeyRelatedField(
        read_only=True, default=serializers.CurrentUserDefault(), source='user.username')
    image_url = serializers.SerializerMethodField('get_image_url')
    
    tutor_availablility = DaySerializer(many=True)

    class Meta:
        model = TutorProfile
        fields = '__all__'

class TutorProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = TutorProfile
        fields = '__all__'
        read_only_fields = ('user',)
  • Related