Django Rest框架:按用户相关字段排序

Django Rest框架:按用户相关字段排序,django,django-rest-framework,django-queryset,serialization,Django,Django Rest Framework,Django Queryset,Serialization,我有一些产品,用户可以将其中一些标记为他最喜欢的产品 收藏夹被建模为用户配置文件和产品之间的多对多关系 我现在想通过API调用获取产品,但首先按收藏夹排序,然后按其他所有内容排序。现在,由于这取决于当前的请求,我无法通过Product.objects.all().order_by(…)执行此操作,因为模型不知道当前用户,而且我现在知道通过序列化程序或ModelViewSet告诉查询的方法 我尝试从ModelViewSet中的用户配置文件中获取两个查询集,一个包含所有产品,一个包含所有收藏夹,如下

我有一些产品,用户可以将其中一些标记为他最喜欢的产品

收藏夹被建模为用户配置文件和产品之间的多对多关系

我现在想通过API调用获取产品,但首先按收藏夹排序,然后按其他所有内容排序。现在,由于这取决于当前的请求,我无法通过
Product.objects.all().order_by(…)
执行此操作,因为模型不知道当前用户,而且我现在知道通过序列化程序或ModelViewSet告诉查询的方法

我尝试从
ModelViewSet
中的用户配置文件中获取两个查询集,一个包含所有产品,一个包含所有收藏夹,如下所示:

class ProductViewSet(viewsets.ModelViewSet):
    serializer_class = ProductCreateSerializer
    # ...

    def get_queryset(self):
        favorited_products = self.request.user.profile.favorites.all()
        products = Product.objects.all()

        queryset = favorited_products | products

        return queryset
这是可行的,因为实体保持这种顺序。但是这个视图返回了几百个实体,所以当我试图用
return queryset[:30]
限制queryset时,默认的顺序似乎接管了它

我想做的事情很容易实现吗?有人已经解决了类似的问题吗

以下是我的模型:

class Product(models.Model):
    product_name = models.CharField(max_length=200)
    # ...


    def __unicode__(self):
        return self.product_name


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    favorites = models.ManyToManyField(Product)

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.get_or_create(user=instance)

    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()
和我的序列化程序:

class FavoriteField(serializers.BooleanField):
    def get_attribute(self, instance):

        return self.context['request'].user.profile.favorites.filter(pk=instance.pk).exists()

class ProductSerializer(serializers.ModelSerializer):
    favorite = FavoriteField()

    def update(self, instance, validated_data):
        instance = super().update(instance, validated_data)
        is_favourite = validated_data.get('favorite')  # can be None
        if is_favourite is True:
            self.context['request'].user.profile.favorites.add(instance)
        elif is_favourite is False:
            self.context['request'].user.profile.favorites.remove(instance)
        return instance

我使用Count、Case和IntegerField找到了一个解决方案:

user_id = self.request.user.pk
queryset = Product.objects \
        .annotate(favorited=Count(Case(When(favorited_by__user__pk=user_id, then=1), output_field=IntegerField()))) \
        .order_by("-favorited")

很好的解决方法!我想指出kwarg应该是
output\u字段
谢谢你,@wasabigeek。我还修复了kwarg。