0

私はいくつかの製品を持っていますが、そのうちの1つはユーザーがお気に入りの製品としてマークすることができます。Django Rest Framework:ユーザー依存フィールドで注文する

お気に入りは、ユーザープロファイルと製品の間の多対多の関係としてモデル化されています。

私は今、APIコールを介して製品を入手したいと思いますが、最初にお気に入りで注文し、その他はすべて注文します。これは現在のリクエストに依存するので、モデルは現在のユーザーを知らないので、Product.objects.all().order_by(...)でこれを行うことはできません。シリアライザまたは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 

これが作業を行います。

は、私は2つのこのようなクエリセット、すべての製品との1、 ModelViewSetでのユーザープロファイルからのすべてのお気に入りのものを、取得しようとしました。しかし、このビューは数百のエンティティを返すので、 return queryset[:30]でクエリセットを制限しようとすると、デフォルトの順序が引き継がれるようです。

達成しようとしていることは簡単に達成可能ですか?既に誰かが同様の問題を解決しましたか?

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 

答えて

2

私はカウント、ケースと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") 
+0

偉大な回避策を!私はkwargが 'output_field'であるべきことを指摘したいと思います – wasabigeek

+0

ありがとう、@ wasabigeek。私もkwargを修正しました。 –

関連する問題