jazzband / django-polymorphic

Improved Django model inheritance with automatic downcasting
https://django-polymorphic.readthedocs.io
Other
1.61k stars 275 forks source link

Integration with django-filter: 'Meta.fields' must not contain non-model field names #520

Open mfoglio opened 2 years ago

mfoglio commented 2 years ago

Hello, I have the following models representing some Data that can be created by an Annotator which can either be a human UserAnnotator or an AI AiModelAnnotator

class Annotator(PolymorphicModel):
    pass

class UserAnnotator(Annotator):
    user = models.ForeignKey(
        get_user_model(),
        on_delete=models.PROTECT,
        default=None
    )

class AiModelAnnotator(Annotator):
    ai_model = models.CharField(max_length=255)
    version = models.CharField(max_length=16, default=None, null=True)

class Data(models.Model):
    annotator = models.ForeignKey(Annotator, on_delete=models.PROTECT)

I am using django-rest-framework and django-filter to expose an API endpoint where I can look for data produced by a specific AI model. The serializers are the following:

class AiModelAnnotatorSerializer(serializers.ModelSerializer):
    class Meta:
        model = AiModelAnnotator
        fields = '__all__'

class UserAnnotatorSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserAnnotator
        fields = '__all__'

class AnnotatorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Annotator
        fields = '__all__'

class AnnotatorPolymorphicSerializer(PolymorphicSerializer):
    model_serializer_mapping = {
        Annotator: AnnotatorSerializer,
        AiModelAnnotator: AiModelAnnotatorSerializer,
        UserAnnotator: UserAnnotatorSerializer,
    }

class AnnotationSerializer(serializers.ModelSerializer):
    annotator = serializers.PrimaryKeyRelatedField(queryset=Annotator.objects.all())
    class Meta:
        model = Annotation
        fields = '__all__'

And the viewset is:

class AnnotationTrainingViewSet(
        mixins.CreateModelMixin,
        mixins.ListModelMixin,
        mixins.RetrieveModelMixin,
        viewsets.GenericViewSet
    ):
    queryset = Annotation.objects.all()
    serializer_class = AnnotatorPolymorphicSerializer
    filterset_fields = ('annotator', 'annotator__ai_model')

When I try to call the GET endpoint with the error 'Meta.fields' must not contain non-model field names: annotator__ai_model which is caused by adding annotator__ai_model to the AnnotationTrainingViewSet. Without specifying annotator__ai_model the code works fine but of course I can't use django-filter as I'd like to. Is this the expected behavior? Is django-filter supported?

lvlgl commented 1 year ago

I am also searching for a solution to this issue. While I have been able to find workarounds for some cases, these workarounds are not able to accommodate different types of lookups. Therefore, I am hoping that @vdboor will provide an answer soon clarifying how we can properly solve this problem