Django - 注释查询是否当前用户关注查询用户

Django - annotate query for if queried user is followed by current user

所以我在下面给出了这段代码 user_uuid 我查找用户的信息。所有 request 都带有一个包含当前用户 uuid 的身份验证令牌。如果当前用户查询了他们自己的个人资料,那么 is_current_user 键应该为真,这是通过 item['is_current_user'] = user_uuid == request.user.uuid 行完成的,然后我有另一个标志来判断当前用户是否正在关注被查询的用户item['is_following'] = FollowUser.objects.filter(follower=str(request.user.uuid), followee=user_uuid).exists()。如您所见,这些都是非常丑陋的 hack,我想知道我是否可以将这些值添加到 annotate 函数中。

def get_user_info(request, user_uuid):
    try:
        query_annotated = User.objects.annotate(
            follower_count=Count('followee_id', distinct=True),
            followee_count=Count('follower_id', distinct=True)).get(pk=user_uuid)
    except User.DoesNotExist as e:
        return Response(dict(error=str(e),
                             user_message='User not found.'),
                        status=status.HTTP_404_NOT_FOUND)
    serializer = FullUserSerializer(query_annotated)
    # TODO: This is a hack the above annotation is not working
    item = serializer.data
    item['is_following'] = FollowUser.objects.filter(follower=str(request.user.uuid), followee=user_uuid).exists()
    item['is_current_user'] = user_uuid == request.user.uuid
    return Response(item, status=status.HTTP_200_OK)

版本 2

FullUserSerializer.py

class FullUserSerializer(serializers.ModelSerializer):
    follower_count = serializers.IntegerField()
    followee_count = serializers.IntegerField()
    is_following = serializers.BooleanField()
    is_current_user = serializers.BooleanField()

    class Meta:
        model = User
        fields = ('uuid', 'username', 'avatar', 'created', 'follower_count',
                  'followee_count', 'is_current_user', 'is_following')

view.py

def get_user_info(request, user_uuid):
    try:
        query_annotated = User.objects.annotate(
            follower_count=Count('followee_id', distinct=True),
            followee_count=Count('follower_id', distinct=True),
            is_following=Exists(
                FollowUser.objects.filter(
                    follower=str(request.user.uuid),
                    followee=OuterRef("pk")
                )
            ),
            is_current_user=Case(
                When(
                    pk=str(request.user.uuid),
                    then=Value(True)
                ),
                default=Value(False),
                output_field=BooleanField(),
            ),
        ).get(pk=user_uuid),
    except User.DoesNotExist as e:
        return Response(dict(error=str(e),
                             user_message='User not found.'),
                        status=status.HTTP_404_NOT_FOUND)
    serializer = FullUserSerializer(query_annotated)
    # TODO: This is a hack the above annotation is not working
    # item = serializer.data
    # item['is_following'] = FollowUser.objects.filter(follower=str(request.user.uuid), followee=user_uuid).exists()
    # item['is_current_user'] = user_uuid == request.user.uuid
    return Response(serializer.data, status=status.HTTP_200_OK)

model.py

class User(AbstractDatesModel):
    uuid = models.UUIDField(primary_key=True)
    username = models.CharField(max_length=USERNAME_MAX_LEN, unique=True, validators=[
        MinLengthValidator(USERNAME_MIN_LEN)])
    created = models.DateTimeField('Created at', auto_now_add=True)
    updated_at = models.DateTimeField('Last updated at', auto_now=True, blank=True, null=True)
    avatar = models.ImageField(upload_to=avatar_directory_path, blank=True, null=True)

    @property
    def avatar_url(self):
        return self.avatar.url

试试这个:

from django.db.models import Case, Exists, OuterRef, When, Value


query_annotated = User.objects.annotate(
    # ...
    is_following=Exists(
        FollowUser.objects.filter(
            follower=str(request.user.uuid), 
            followee=OuterRef("pk")
        )
    ),
    is_current_user=Case(
        When(
            pk=request.user.uuid, 
            then=Value(True)
        ),
        default=Value(False),
        output_field=BooleanField(),
    ),
).get(pk=user_uuid)