Django-filter: Meta.fields look-ups no longer work with annotated fields in 2.0

Created on 23 Nov 2018  路  2Comments  路  Source: carltongibson/django-filter

I've recently upgraded to 2.0, which apart from this particular issue, went quite well. I am using query-set annotations as quick read-only fields. I define supported look-ups for these fields in Meta.fields, but as of 2.0, these now work only for actual model fields:

class MySerializer(ModelSerializer):
    annotated_field = IntegerField(read_only=True)

    class Meta:
        model = MyModel
        fields = ('model_field', 'annotated_field')


class MyFilterSet(FilterSet):
    annotated_field = NumberFilter()

    class Meta:
        model = MyModel
        fields = {'model_field': ['exact', 'gt', 'lt'], # <-- Works as expected.
                  'annotated_field': ['exact', 'gt', 'lt']}  # <-- Doesn't work for me.


class MyViewSet(ModelViewSet):
    serializer_class = MySerializer
    filterset_class = MyFilterSet
    filter_backends = (DjangoFilterBackend,)
    queryset = MyModel.objects.annotate(
        annotated_field=Coalesce('field_a', 'field_b', 'field_c'))

As you can see above, my Meta.fields defines exact, gt and lt as look-ups available to both the model and the annotated field. For some reason, I can't get the annotated field look-ups to work and I am sure this was OK in 1.x. Has this functionality been deprecated or accidentally removed?

Thank you in advance.

Most helpful comment

Hey @rpkilby, thanks for getting back to me. I have to admit I didn't look into it properly until recently (separated the functionality into a blank test project with django-filter 1.x installed) and I can confirm this (probably) never worked.

Not sure what I was thinking. I'll be using a more verbose, but functional way of achieving this:

class MyFilterSet(FilterSet):
    field = NumberFilter()
    field__gt = NumberFilter(field_name='field', lookup_expr='gt')
    field__lt = NumberFilter(field_name='field', lookup_expr='lt')
    ...

All 2 comments

Hi @markgajdosik. I don't believe this functionality ever existed. Meta.fields works by inspecting a model's fields during FilterSet class creation. Annotations only exist on a queryset, which is provided during per-instance initialization.

Do you know what version may have worked previously? Can you print out the following:

  • MyFilterSet.declared_filters
  • MyFilterSet.base_filters

Hey @rpkilby, thanks for getting back to me. I have to admit I didn't look into it properly until recently (separated the functionality into a blank test project with django-filter 1.x installed) and I can confirm this (probably) never worked.

Not sure what I was thinking. I'll be using a more verbose, but functional way of achieving this:

class MyFilterSet(FilterSet):
    field = NumberFilter()
    field__gt = NumberFilter(field_name='field', lookup_expr='gt')
    field__lt = NumberFilter(field_name='field', lookup_expr='lt')
    ...
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jnegro picture jnegro  路  3Comments

csarcom picture csarcom  路  3Comments

chromakey picture chromakey  路  5Comments

hakib picture hakib  路  3Comments

sassanh picture sassanh  路  4Comments