Search code examples
djangodjango-rest-frameworkswaggerdjango-filterdrf-yasg

drf-spectacular issue with filterset_fields


I am trying to implement drf-spectacular to an existing Django REST API.

However I am getting the following error, when attempting to run

./manage.py spectacular --file schema.yml

Error:

python3.7/site-packages/django_filters/filterset.py", line 352, in get_filters
    "%s" % ', '.join(undefined)
TypeError: 'Meta.fields' contains fields that are not defined on this FilterSet: client, tenant_id, subtenant_id, data_stream_id

The filters do work, but don't seem to play nicely with the drf-spectacular lib. Can anyone please advise on how this might be solved?

Specs as follows:

Python                3.7.2
Django                3.0.2    
django-filter         2.2.0    
django-rest-framework 0.1.0    
djangorestframework   3.12.1   
drf-spectacular       0.12.0 

Viewset example:

class subModelViewSet(viewsets.ModelViewSet):
    """Standard ViewSet for the DataStream Model."""
    queryset = DataStream.objects.all()
    serializer_class = DataStreamSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ('client', 'tenant_id', 'subtenant_id', 'data_stream_id',)

Serializer example:

class DataStreamSerializer(serializers.ModelSerializer):
    """Class to validate an uploaded DataStream."""

    class Meta:
        """Nested Meta Class."""

        model = DataStream
        fields = '__all__'

Solution

  • Turns out it was a Viewset that was trying to apply filterset_fields on a subModel that did not directly contain those fields, but rather referenced by ForeignKey on another Parent Model. While I thought these filters were working as expected, I think the actual filtering on those fields was being performed by middleware in this case.

    Removing the fields from the Viewset allows the schema to be generated with no issue. I am able to access the /docs page fully rendered and /schema endpoint working. Very impressed with drf-spectacular thus far.

    example model:

    class DataSteam(models.Model):
        """Class for DataSteam Model."""
        client = models.CharField(max_length=200)
        tenant_id = models.CharField(max_length=200)
        subtenant_id = models.CharField(max_length=200)
        data_stream_id = models.CharField(max_length=200)
    
    class subModel(models.Parent):
        """Class for storing linked datastream records."""
        ds = models.ForeignKey(DataStream, on_delete=models.CASCADE)