0

I have a question here

I have two models

Tag Model

class Tag(models.Model):
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='author')
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

Profile Model

class Profile(models.Model):
    profiler = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='contour')
    bio = models.TextField(blank=True, null=True)
    tags = models.ManyToManyField(Tag, blank=True, related_name='keywords')
    image = models.ImageField(default='avatar.jpg', upload_to='images', blank=True, null=True)

    def __str__(self):
        return f'{self.profiler}'

Tag Serializer

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = '__all__'

Profile Serializer

class ProfileSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True, read_only=True)

    class Meta:
        model = Profile
        fields = ['id',  # List All fields Exclude profiler => OneToOne field name
                  'bio', 'description',
                  'tags',
                  'image',
                  'birthDate', 'created', 'updated',
                  ]
        depth = 1

Profile Viewset

class ProfileViewSet(viewsets.ModelViewSet):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer
    permission_classes = [IsAuthenticated]

def partial_update(self, request, *args, **kwargs):
    data = request.data

    profile_obj = Profile.objects.update(
        profiler=self.request.user,
        bio=data['bio'],
        image=data['image'],
    )

    profile_obj.save()

    for tag in data['tags']:
        tag_obj = Tag.objects.update_or_create(
            creator=self.request.user,
            name=tag['name'],  # name => Field Name in Tag Model
        )

        print(tag_obj)
        profile_obj.tags.add(tag_obj)  # tags => ManyToMany Field Name in Profile Model

    serializer = ProfileSerializer(profile_obj)

    return Response(serializer.data)

my aim is to create a new tag if this name is not exist, and also update profile tags

but my code is not working, and I don't know why

Can Any body help please ?

Mohamed Abbase
  • 111
  • 3
  • 15

1 Answers1

0

Finally I found the solution, But it still missing some steps

Profile Serializer

class ProfileSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True)  # tags = ManyToMany Field Name

    class Meta:
        model = Profile

        fields = ['id',  # List All fields Exclude profiler => OneToOne field name
                  'bio', 'description',
                  'tags',
                  'image', 'get_image',
                  'birthDate', 'created', 'updated',
                  ]

    def update(self, instance, validated_data):
        # Clear Existing Tags List Before Creating a New One By user
        instance.tags.clear()

        tags_data = validated_data.pop('tags')
        instance = super(ProfileSerializer, self).update(instance, validated_data)

        for tag_data in tags_data:
            tag_qs = Tag.objects.filter(name__iexact=tag_data['name'])

            if tag_qs.exists():
                tag = tag_qs.first()
            else:
                tag = Tag.objects.create(**tag_data, creator=self.instance.profiler)

            instance.tags.add(tag)

        return instance

It Worked Like a charm but the problem is: when I want to partial update of fields and i did't submit tags field, It raises error

{
    "tags": [
        "This field is required."
    ]
}

Can some one help to keep my tags list as it is when the updated data missing tags field

Thanks in-advance

Mohamed Abbase
  • 111
  • 3
  • 15