从外键获取用户对象

时间:2018-08-26 17:07:56

标签: python django django-rest-framework

我正在使用Django Rest Framework。我有两个模型,如下所示:

class Following(models.Model):
    target = models.ForeignKey('User', related_name='followers', on_delete=models.CASCADE, null=True)
    follower = models.ForeignKey('User', related_name='targets', on_delete=models.CASCADE, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '{} is followed by {}'.format(self.target, self.follower)

class User(AbstractBaseUser):
    username    = models.CharField(max_length=15, unique=True)

    email       = models.EmailField(max_length=100, unique=True)

我想拥有一个API,该API将返回用户拥有的所有关注者。但是,我不希望以Following模型格式返回它,我希望以这种格式将关注者作为用户返回:

[
 {
     "username": Bob,
     "email": example@example.com
 },
 {
     "username": Charlie,
     "email": example@example.com
 }
]

现在,我有这样的东西:

class FollowingAPIView(ListAPIView):
    serializer_class = FollowingSerializer

    def get_queryset(self):
        return Following.objects.filter(target=3)

class FollowingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Following
        fields = ('follower', 'target')

这仅显示followertarget我不想要这个。我需要来自User的实际数据。此外,我将target=3用作占位符只是为了进行测试。

1 个答案:

答案 0 :(得分:5)

您应该为User而不是following使用序列化程序:

class UserSerializer(serializers.ModelSerializer):
    is_following = serializer.IntegerField()
    class Meta:
        model = User
        fields = ('username', 'email', 'is_following')

另外,在视图中更改查询集,如下所示:

from django.db import models
from rest_framework.generics import get_object_or_404

class FollowingAPIView(ListAPIView):
    serializer_class = FollowingSerializer

    ### so add this method to get the requested user based on the username in the url
    def get_requested_user(self):
        ##get the user based on the user name in url
        filter_kwargs = {'username': self.kwargs['username']} 
        obj = get_object_or_404(User.objects.all(), **filter_kwargs)
        return obj

    def get_queryset(self):
         requested_user = self.get_requested_user()
         return User.objects.filter(targets__target=requested_user)\
             .annotate(is_following=models.Count('followers', filter=models.Q(followers__follower=requested_user), distinct=True))

如果您使用的是Django <2.0,则您的get_queryset应该类似于:

    def get_queryset(self):
         requested_user = self.get_requested_user()
         return User.objects.filter(targets__target=requested_user)\
             .annotate(is_following=models.Count(models.Case(models.When(models.Q(followers__follower=requested_user), 1))))

因为要返回用户列表,而不是“跟随”实例。仅使用以下命令过滤(上述过滤器中的targets__)用户target中的Following是当前经过身份验证的用户(至少在其目标之一中)。

已更新

另外,将您的网址更改为以下内容:

path('/api/followers/<username>/', FollowingAPIView.as_view(), name='get_user_followers')