How to return a value from another model using the Django Rest Framework?

Question:

When I query all the comments of the post, I want to return the user’s username.

My two Models:

class Comment(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE)
    post = models.ForeignKey(
        Post, on_delete=models.CASCADE, null=False, blank=False)
    title = models.TextField()
    date = models.DateField(auto_now=True)

class User(AbstractUser):
    objects = UserManager()

    username = models.CharField(max_length=60, unique=True)
    avi_pic = models.ImageField(
        _('avi_pic'), upload_to=aviFile, null=True, blank=True)

My Comments Serializer:

class CommentSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField('get_username_from_user')
    avi_pic = serializers.SerializerMethodField('get_avi_pic')

    class Meta:
        model = Comment
        fields = '__all__'

    def get_username_from_user(self, comment):
        username = comment.user.username
        return username
    
    def get_avi_pic(self, comment):
        request = self.context['request']
        avi_pic = comment.user.avi_pic.url
        return request.build_absolute_uri(avi_pic)

My Comments View:

class CommentView(APIView):
    authentication_class = [authentication.TokenAuthentication]
    permission_class = [permissions.IsAuthenticated]
    serializer_class = CommentSerializer
    
    # Get all comments from current post
    def get(self, request):
        post_id = request.data.get('id')
        post = Post.objects.get(id=post_id)
        comment = Comment.objects.filter(post=post).values()

        serializer = CommentSerializer(comment)

        return Response(serializer.data, status=status.HTTP_200_OK)

In my console I get: ‘QuerySet’ object has no attribute ‘user’

Appreciate any help!!

Asked By: jdez

||

Answers:

In my humble opinion, your problem is not having a ForeignKey for the "User" model, meaning whatever model you are trying to render doesn’t have a column named ‘user’. I’d do something like this:

models.py

class User(AbstractUser):
    pass

    def __str__(self):
        return f"{self.username}"

class Comment(models.Model):
    comment = models.TextField(max_length=300, null=True)
    creation_date = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    whatever_name = models.ForeignKey(whatever_model_to_relate, on_delete=models.CASCADE, related_name="comments")

forms.py

class CommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ['comment']   
        widgets = {
          'comment': forms.Textarea(attrs={'rows':4, 'cols':100}),
        }

views.py

@login_required
def whatever_function(request, id):
    whatever_name = whatever_related_model.objects.get(id=id)
    return render(request, "template.html", {
        "whatever_name_for_template": whatever_name,
        "commentform": CommentForm()
    })

template.html

  {% for comment in whatever_related_model.comments.all %}
      <div class="card p-1 m-2 col-lg-12 col-sm-12">
          <div class="card-body">
              <h5 class="card-title">{{ comment.user }}</h5>
              <h6 class="card-subtitle mb-2 text-muted">{{ comment.creation_date }}</h6>
              {{ comment.comment }}
          </div>
      </div>
  {% endfor %}

Hopefully I didn’t get sidetracked from your question.

Answered By: CVilla90

In views.py:

comment = Comment.objects.filter(post=post)

In serializer.py:

def get_username_from_user(self, comment):
    username = comment.user.username
    return username

In views.py:

def get(self, request):
    ...
    serializer = CommentSerializer(comment, many=True)
    ...
Answered By: Bhavya Peshavaria