Search code examples
djangodjango-rest-frameworkdjango-filter

Django REST Framework filter by Foreign key


First of all, please consider that I'm very new in Django so I'm not really sure about what I'm looking for.

I have a model called Product:

class Product(models.Model):
   name = models.CharField('Name', max_length=100)
   ...

One Product can have several variants so I created another model called ProductVariant which has a ForeignKey to Product.

class ProductVariant(models.Model):
   name = models.CharField('Name', max_length=100)
   product = models.ForeignKey(Product,
                            verbose_name='Produkt',
                            related_name='productvariants',
                            on_delete=models.CASCADE)
...

I want to return only the Products that have Variants but I don't know how to access that information from the Product Filter or Product Serializer, since the ForeignKey is on the ProductVariant model.

Any ideas? I know this is basic Django but I'm completely new, any help would be really appreciated.

This is my Product Filter:

class ProductFilter(filters.FilterSet):

class Meta:
    model = Product
    fields = ['id', 'name']

The Product Serializer:

class ProductSerializer(serializers.ModelSerializer):

    class Meta:
       model = Product
       fields = ('id', 'name')

The Product ViewSet:

class ProductViewSet(ModelViewSet):
   queryset = Product.objects.all()
   filterset_class = ProductFilter
   serializer_class = ProductSerializer
   permission_classes = [IsAuthenticated]

Solution

  • You can control what goes into the ModelView response by changing the queryset field. If you want to see only those Products that have a variant, try filtering for those, that have a variant with a non-None name field (if there is one, it will have a value).

    class ProductViewSet(ModelViewSet):
       queryset = Product.objects.filter(productvariants__name__isnull=False).distinct()
       filterset_class = ProductFilter
       serializer_class = ProductSerializer
       permission_classes = [IsAuthenticated]
    

    I have added a .distinct() call so that each Product only appears once.