Home > Mobile >  Adding a custom, non-model attribute to query set in Django?
Adding a custom, non-model attribute to query set in Django?

Time:12-05

Newbie to DRF and have a model called posts. And another called user. The post object looks as follows:

class Post(models.Model):
    """
        Post model
    """

    title = models.CharField(max_length=250)
    body = models.TextField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL,
                               on_delete=models.CASCADE,
                               related_name='forum_posts')
    parent_post = models.ForeignKey('self',
                                    on_delete=models.CASCADE,
                                    blank=True,
                                    null=True)
    time_stamp = models.DateTimeField(default=timezone.now)

    objects = models.Manager()

The serializer for this model is:

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Post
        fields = ('id', 'title', 'body', 'parent_post', 'author', 'time_stamp')
        extra_kwargs = {'id': {'read_only': True},
                        'author': {'read_only': True}}

When returning data for this model, I want to add an extra attribute to each object within the query set called "author_username". The username should be the username belonging to the post's author id. I also want to do this without modifying the model to add another attribute such as "author_username" since this'll be redundant (already have an FK for author). So, ideally, the json for an object would look like:

'post_id': 1
'post_title': 'Example post'
'post_body': 'Example post'
'author_id': 1
'parent_post_id': null
'time_stamp': '2022'
'author_username': 'testUser'

How can I go about doing this?

Here's my view:

class PostList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = models.Post.objects.all()
    serializer_class = serializers.PostSerializer

CodePudding user response:

The source argument can be passed to a serializer field to access an attribute from a related model

class PostSerializer(serializers.ModelSerializer):

    author_username = serializers.CharField(source="author.username", read_only=True)

    class Meta:
        model = models.Post
        ...

You should add a select_related call to your view's queryset

class PostList(generics.ListCreateAPIView):
    ...
    queryset = models.Post.objects.select_related('author')
    ...
  • Related