Search code examples
pythondjangographqldjango-filtergraphene-django

How can I use django-filter's DateTimeFromToRangeFilter with Graphene?


I'm attempting to use an instance of django-filter's DateTimeFromToRangeFilter in conjunction with a custom FilterSet. However, this does not work when I attempt to do the following:

class CustomFilterSet(FilterSet):
    modified = django_filters.IsoDateTimeFromToRangeFilter()

    class Meta:
        fields = "__all__"
        model = Custom

This does not result in additional fields or annotations being created, like I'd expect based on the docs. Something like:

f = F({'modified_after': '...', 'modified_before': '...'})

If I inspect the single field (modified) which has been added to my DjangoFilterConnectionField, I see the following:

{'creation_counter': 395, 'name': None, '_type': <String meta=<ScalarOptions name='String'>>, 'default_value': Undefined, 'description': None, 'deprecation_reason': None}

So, how do I configure this filter such that I can write a query like the following?

query {
    allTheSmallThings(
        modified_before: "2023-09-26 17:21:22.921692+00:00"
    ) {
        edges {
            node {
                id
            }
        }
    }
}

UPDATE: I can confirm that I'm able to use the FilterSet subclass as documented. The issue seems to be with the fields that are/not being generated by Graphene.


Solution

  • To filter a DateTime field using a custom FilterSet in Graphene-Django, you can follow these steps:

    1. Define a custom DateTime filter field using IsoDateTimeFromToRangeFilter from django-filter in your custom FilterSet class.
    2. Make sure that the filter field name you define matches the name you will use in your GraphQL query.
    3. Ensure that your GraphQL schema includes the custom FilterSet and field names correctly.

    Here's how you can modify your code to achieve this:

    Assuming you have a model named Custom, here's how you can define a custom FilterSet and integrate it into your GraphQL schema:

    import django_filters
    import graphene
    from graphene import relay
    from graphene_django.filter import DjangoFilterConnectionField
    from graphene_django.types import DjangoObjectType
    
    from .models import Custom  # Import your Custom model here
    
    class CustomFilterSet(django_filters.FilterSet):
        modified_before = django_filters.IsoDateTimeFilter(
            field_name='modified', lookup_expr='lte'
        )
        modified_after = django_filters.IsoDateTimeFilter(
            field_name='modified', lookup_expr='gte'
        )
    
        class Meta:
            model = Custom
            fields = []
    
    class CustomNode(DjangoObjectType):
        class Meta:
            model = Custom
            interfaces = (relay.Node,)
    
    class Query(graphene.ObjectType):
        all_the_small_things = DjangoFilterConnectionField(
            CustomNode, filterset_class=CustomFilterSet
        )
    
    schema = graphene.Schema(query=Query)
    

    With this setup, you can use the modified_before and modified_after filters in your GraphQL query like this:

    query {
        allTheSmallThings(
            modified_before: "2023-09-26T17:21:22.921692Z"
        ) {
            edges {
                node {
                    id
                    # Add other fields you want to retrieve
                }
            }
        }
    }
    

    Make sure to adjust the field_name and lookup_expr values in the CustomFilterSet to match your model's field name and the filter conditions you want to apply.

    Additionally, ensure that you have imported the necessary modules and set up your GraphQL schema correctly.