简体   繁体   中英

How to annotate queryset if object in ManyToManyField

I am trying to build a small social network where users can like posts. I am using Django 3.1.7. I have defined my model for the post as follows:

class Post(models.Model):
    date_published = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.CharField(max_length=240, blank=False, default=None)
    user_like = models.ManyToManyField(User, blank=True, related_name='likes')

    def __str__(self):
        return f'{self.user.username} posted \"{self.content}\" on {self.date_published}'

From my views.py I want to return the posts with an annotation of whether the current user has liked a given post. I am trying as follows:

def index(request):

    posts = Post.objects.all().annotate(
        likes=Count('user_like')).order_by('-date_published')

    if request.user.is_authenticated:
        posts = Post.objects.all().annotate(
            likes=Count('user_like'), liked=request.user in 'user_like'.all).order_by('-date_published')
    
    paginator = Paginator(posts, 10)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, "network/index.html", {
        'post_form': PostForm(),
        'page_obj': page_obj
    })

But unfortunately, I can not make the query work. I assume that the part where I check if the user is in the relationship is wrong ( liked=request.user in 'user_like'.all ) as it is treating 'user_like' as str and not as the field in the Post.

How should I annotate the posts to include whether the user has liked them or not based on the ManyToManyField between them? Thanks

You can work with an Exists subquery [Django-doc] :

from django.db.models import Exists, OuterRef

posts = Post.objects.annotate(
    likes=Count('user_like'),
    liked=Post.user_like.through.objects.filter(
        post_id=OuterRef('pk'),
        user_id=request.user.pk
    )
).order_by('-date_published')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM