Valentin
Valentin

Reputation: 301

Nested JSON and HyperlinkedModelSerializer problem

I'm working on a tweet App. I have 2 main models : Tweets and Comments. I'm using HyperlinkedModelSerializer to get absolute url for my comments instances with the "url" added in the field. But when It comes to display the comments inside my tweet JSON format, i have this error :

`HyperlinkedIdentityField` requires the request in the serializer context. Add `context={'request': request}` when instantiating the serializer.

This error is gone when I remove the url from the field. Here is my Comment Model :

class CommentManager(models.Manager):
def filter_by_instance(self, instance):
    content_type = ContentType.objects.get_for_model(instance.__class__)
    obj_id = instance.id
    qs = super(CommentManager, self).filter(content_type=content_type, object_id=obj_id)
    return qs


class Comment(models.Model):
    content = models.TextField(max_length=150)
    author = models.ForeignKey(
        User,
        on_delete = models.CASCADE
    )
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField(blank=True)
    content_object = GenericForeignKey('content_type', 'object_id')
    parent = models.ForeignKey(
        "self",
        on_delete = models.CASCADE,
        blank=True,
        null=True
    )
    datestamp = models.DateTimeField(auto_now_add=True)
    objects = CommentManager()

    def __str__(self):
        return str(self.content[:30])

    def save(self):
        self.object_id = self.parent.id
        super(Comment, self).save()

    def children(self):
        return Comment.objects.filter(parent=self)

    @property
    def is_parent(self):
        if self.parent is None:
            return False
        return True

Here is my comment serializer :

class CommentSerializer(serializers.HyperlinkedModelSerializer):

children = serializers.SerializerMethodField()
datestamp = serializers.SerializerMethodField()

def get_datestamp(self, obj):
    return obj.datestamp.date()

def get_children(self, obj):
    qs = obj.children()
    return ChildrenCommentSerializer(qs, many=True).data

class Meta:
    model = Comment
    fields = [
        "url",
        "datestamp",
        "content",
        "is_parent",
        "object_id",
        "children"
    ]


class ChildrenCommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = [
            "content"
        ]

And finally my tweet serializer :

class TweetSerializer(serializers.ModelSerializer):

author = serializers.SlugRelatedField(slug_field="username", queryset=User.objects.all())
comments = serializers.SerializerMethodField()
datestamp = serializers.SerializerMethodField()

def get_datestamp(self, obj):
    return obj.datestamp.date()

def get_comments(self, obj):
    qs =  Comment.objects.filter_by_instance(obj)
    print()
    print()
    print(CommentSerializer(qs, many=True))
    print()
    print()
    return CommentSerializer(qs, many=True).data

class Meta:
    model = Tweet
    fields = ["datestamp", "id", "content", "author", "nb_likes", "nb_comments", "slug", "comments"  ]

def to_representation(self, obj):
    representation = super().to_representation(obj)
    if obj.nb_likes > 50:
        representation['super_popular'] = True
    return representation

I do not understand how and where in the code i should add the "context={'request': request}"

Upvotes: 0

Views: 433

Answers (1)

yson
yson

Reputation: 276

place it when instantiating the serializer

class ViewExample(APIView):

  def get(self, request, pk, format=None):
    listexample = Example.objects.all()
    serializer = ExampleSerializer(listexample, many=True, context={'request':request})
    return Response(serializer.data, status=status.HTTP_200_OK)

Upvotes: 1

Related Questions