我有一些产品,其中用户可以将其中一些标记为他喜欢的产品。
收藏夹被建模为用户配置文件和产品之间的许多关系。
我现在想通过API呼叫获取产品,但首先按收藏夹订购,其次是其他所有内容。现在,由于这取决于当前请求,因此我无法通过Product.objects.all().order_by(...)
进行此操作,因为该模型不知道当前用户,并且我现在知道通过序列化器或ModelViewSet告诉查询的方法。
我尝试获取两个QuerySet,一个带有所有产品,一个来自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
我已经找到了一个解决方案,使用计数,案例和整数:
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")