0

I'm learning Django and used Sqlite3 for my site until today, I changed the database into Postgres. My site kind of mimics Facebook. I have a ListView that will list all posts. In get_queryset(), I annotate each post with some additional info, such as number of likes and dislikes, number of comments, have current logged in user followed the owner of the post. I also paginated the result so that my site only displays 5 post per page. Here is my code:

class PostListView(FormMixin, ListView):
model = Post
paginate_by = 5
template_name = "network/newsfeed.jinja"
body_title = "All Posts"
context_object_name = "posts"
form_class = PostCreateForm

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['form'] = self.get_form()
    context['body_title'] = self.body_title
    return context

def get_queryset(self):
    queryset = Post.objects.select_related('owner').annotate(
        comment_count=Count('comments', distinct=True),
        like_count=Count(
            Case(
                When(likes__is_like=True, then=Value(1)),
                output_field=IntegerField
            ),
            distinct=True
        ),
        dislike_count=Count(
            Case(
                When(likes__is_like=False, then=Value(1)),
                output_field=IntegerField
            ),
            distinct=True
        ),
    ).order_by('-created_time')  # improve: do we need query all?
    if self.request.user.is_authenticated:
        return queryset.annotate(
            follow_already=Exists(
                Follow.objects.filter(followed=OuterRef('owner'), follower=self.request.user)
            ),
            like_already=Exists(
                Like.objects.filter(owner=self.request.user, post_parent=OuterRef('pk'), is_like=True)
            ),
            dislike_already=Exists(
                Like.objects.filter(owner=self.request.user, post_parent=OuterRef('pk'), is_like=False)
            )
        )
    return queryset.annotate(
        follow_already=Value(False, output_field=BooleanField()),
        like_already=Value(False, output_field=BooleanField())
    )

My site was OK with Sqlite3. But I get an error when changing into Postgres, that occurs on line 17 in get_internal_type() (see the picture), which tells:

TypeError: get_internal_type() missing 1 required positional argument: 'self'

The line raises the error Could you please explain what going on here? I cannot figure it out? I think the reason is the usage of annotation. When I remove them, it works. One more thing, what is the best practice: where to place annotation, I realize that I'm annotating the whole queryset but just use 5 objects in it. Thanks for your reading ^^

Khai Hoan Pham
  • 86
  • 1
  • 2
  • 7

1 Answers1

0

It's still not clear, but I found the root cause. My code was lack of parenthesis in the lines that indicate output_field for annotation for like_count and dislike_count. They should be like this:

output_field=IntegerField() # with parenthesis

Thanks ^^

Khai Hoan Pham
  • 86
  • 1
  • 2
  • 7