Filtering

For adding additional filtering, optional dependency django-filter is required.

import graphene
from graphene import relay
from example_project.app.models import Apartment

from query_optimizer import DjangoObjectType, DjangoConnectionField

class ApartmentNode(DjangoObjectType):
    class Meta:
        model = Apartment
        filter_fields = {
            "street_address": ["exact"],
            "building__name": ["exact"],
        }
        interfaces = (relay.Node,)


class Query(graphene.ObjectType):
    paged_apartments = DjangoConnectionField(ApartmentNode)


schema = graphene.Schema(query=Query)

We can also implement a custom Filterset class to have more control over the filtering.

from example_project.app.models import Apartment

from django_filters import FilterSet

class ApartmentFilterSet(FilterSet):
    # Custom filters can be added here

    class Meta:
        model = Apartment
        fields = [
            "completion_date",
            "street_address",
            "stair",
            "floor",
            "apartment_number",
        ]

These filters are for client side filtering. If you want to do server side filtering, for example to automatically remove rows the user doesn't have access to, we can use the filter_queryset method of the DjangoObjectType class.

from django.db.models import QuerySet
from query_optimizer import DjangoObjectType
from query_optimizer.typing import GQLInfo

class ApartmentType(DjangoObjectType):
    @classmethod
    def filter_queryset(cls, queryset: QuerySet, info: GQLInfo) -> QuerySet:
        # Add your custom filtering here
        return queryset.filter(...)

The optimizer will find this method and use it automatically when this object type is used in a query. No additional queries are performed when using this method as opposed to overriding the get_queryset method itself.