Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django: How to use a query argument in order to exclude nodes matching a specific filter? #305

Closed
vwrobel opened this issue Sep 28, 2016 · 5 comments

Comments

@vwrobel
Copy link

vwrobel commented Sep 28, 2016

First of all, thanks a lot for your work. This project is awesome.

If possible, I would appreciate some hints on setting up a query with 'exclude' filter option.

I have some video items in a Django/Graphene backend setup. Each video item is linked to one owner.
In a React app, I would like to query via GraphQL all the videos owned by the current user on the one hand and all the videos NOT owned by the current user on the other hand.

I could run the following GraphQl query and filter on the client side:

query AllScenes {
  allScenes {
    edges {
      node {
        id,
        name,
        owner {
          name
        }
      }
    }
  }
}

I would rather have two queries with filters parameters directly asking relevant data to my backend. Something like:

query AllScenes($ownerName : String!, $exclude: Boolean!) {
  allScenes(owner__name: $ownerName, exclude: $exclude) {
    edges {
      node {
        id,
        name,
        owner {
          name
        }
      }
    }
  }
}

I would query with ownerName = currentUserName and exclude = True/False yet I just cannot retrieve my exclude argument on my backend side. Here is the code I have tried in my schema.py file:

from project.scene_manager.models import Scene

from graphene import ObjectType, relay, Int, String, Field, Boolean, Float

from graphene.contrib.django.filter import DjangoFilterConnectionField
from graphene.contrib.django.types import DjangoNode

from django_filters import FilterSet, CharFilter





class SceneNode(DjangoNode):

    class Meta:

        model = Scene





class SceneFilter(FilterSet):

    owner__name = CharFilter(lookup_type='exact', exclude=exclude)


    class Meta:

        model = Scene

        fields = ['owner__name']



class Query(ObjectType):


    scene = relay.NodeField(SceneNode)

    all_scenes = DjangoFilterConnectionField(SceneNode, filterset_class=SceneFilter, exclude=Boolean())



    def resolve_exclude(self, args, info):

        exclude = args.get('exclude')

        return exclude




    class Meta:

        abstract = True

My custom SceneFilter is used but I do not know how to pass the exclude arg to it. (I do not think that I am making a proper use of the resolver). Any help on that matter would be much appreciated!

PS: I have asked this question on SO

@vwrobel
Copy link
Author

vwrobel commented Sep 28, 2016

My problem might rather concern django-filters yet I would appreciate any input regarding how to query with exclusion through Graphene.

@vwrobel vwrobel closed this as completed Sep 28, 2016
@vwrobel
Copy link
Author

vwrobel commented Sep 28, 2016

I should have posted in graphene-django. Sorry.

@syrusakbary
Copy link
Member

No worries!

@BossGrand
Copy link
Member

@vwrobel You can use a django method filter

I would just pass in a dict that has a value and exclude

class ExampleFilter(django_filters.FilterSet):
    search_with_exclude = django_filters.MethodFilter()

     def filter_search_with_exclude (self, queryset, value):
         filter_value = value['filter_value']
         exclude_value = value['exclude_value'] 

         queryset = queryset.filter(ownerName=filter_value)
         queryset = queryset.exclude(ownerName=exclude_value)

         return queryset

then you can just pass an object into your graphql query kinda like you would a mutation! :D

@vwrobel
Copy link
Author

vwrobel commented Sep 29, 2016

Thanks a lot @BossGrand!

Updating to graphene-django 1.0, I have been able to do what I wanted with the following query definition:

class Query(AbstractType):

    selected_scenes = DjangoFilterConnectionField(SceneNode, exclude=Boolean())

    def resolve_selected_scenes(self, args, context, info):
        owner__name = args.get('owner__name')
        exclude = args.get('exclude')
        if exclude:
            selected_scenes = Scene.objects.exclude(owner__name=owner__name)
        else:
            selected_scenes = Scene.objects.filter(owner__name=owner__name)
        return selected_scenes

I will try the solution you propose!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants