Home > OS >  How can I serialize custom many-to-many model django?
How can I serialize custom many-to-many model django?

Time:03-31

I have 3 tables on data base: News, CustomUser(not important) and Comment:

class News(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=200)
    text = models.TextField()
    image = models.ImageField(upload_to='news_images/', blank=True)
    author = models.ForeignKey(CustomUser, on_delete=models.SET_DEFAULT, blank=True, default=1)
    tags = models.ManyToManyField(Tags, blank=True)
    published = models.BooleanField(default=False)
    comments = models.ManyToManyField(
        CustomUser,
        related_name='author',
        through='Comments.Comment',
        blank=True,
    )

class Comment(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    text = models.TextField()
    author = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
    event = models.ForeignKey(News, on_delete=models.CASCADE, parent_link=True)

As you can see, the comment is a custom many-to-many model, that links Users and News, and adds some extra data (text of comment itself). I using DRF, so I need to serialize it. I need news serializer to include list of comments with all their fields(like author fields as you can see below on the screenshot).But when i getting one of the news I see that:

{"id":2,"author":{"username":"Admin","email":"[email protected]","first_name":"","last_name":""},"tags":[],"comments":[1],"date":"15.08.2021 10:10","title":"Тест2","text":"тестовая 2","image":"http://127.0.0.1:8000/news_images/Безымянный.png","published":true}

Comments: "comments":[1]

And when I printing during the view-function execution:

self.object = News.objects.filter(pk=pk).first()
print(self.object.comments.all())

I getting this: <QuerySet [<CustomUser: Admin>]> So, instead of a normal representation of comments, I get the authors ID. There are my serializers:

class CommentSerializer(serializers.ModelSerializer):
    author = CustomUserSerializer(source='author.id')
    event = NewsSerializer(source='event.id')

class NewsSerializer(serializers.ModelSerializer):
    author = CustomUserSerializer(read_only=True)
    tags = TagSerializer(required=False, allow_null=True, many=True)
    comments = serializers.PrimaryKeyRelatedField(allow_null=True, many=True, read_only=True)

So, how can I serialize these tables, or maybe organize them in a different way?

P.S. I also tried StringRelatedField instead of PrimaryRelatedField, but it returns author's name.

CodePudding user response:

  1. You have typo in your code: comments in News model must be linked with Comment model, not with CustomUser. That's why you get <QuerySet [<CustomUser: Admin>]>.

  2. To solve "I need news serializer to include list of comments with all their fields", I'd do the following:

class CommentSerializer(serializers.ModelSerializer):
    author = CustomUserSerializer()

    class Meta:
        model = Comment
        exclude = ('event',)  # in your particular case


class NewsSerializer(serializers.ModelSerializer):
    author = CustomUserSerializer(read_only=True)
    tags = TagSerializer(required=False, allow_null=True, many=True)
    comments = CommentSerializer(many=True)
    
    class Meta:
        model = News
        fields = "__all__"

I advise you to exclude event in CommentSerializer because you'll have this info in your NewsSerializer so it won't be repeated for each comment.

  • Related