Repository: graphql-python/graphene-django

Issue:
Filtering not working correctly with 2.6.0
Related to #750. Appreciate the fix for this problem!!

### Problem
When using filter_fields I get an error about using wrong types which started appearing in 2.4.0.
`Variable "userEmail" of type "String" used in position expecting type "ID".` The error does not occur with graphene-django 2.3.2

### Context
- using django-filter 2.2.0
- django 2.4.0
- graphene-django 2.6.0
### 

**model.py**
```
class Membership(TimeStampedModel):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)



class User(TimeStampedModel, AbstractBaseUser, PermissionsMixin):
    email = EmailField(unique=True, verbose_name=_('email'))

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()
```

**Schema.py**
```
class MembershipNode(DjangoObjectType):
    class Meta:
        model = Membership
        filter_fields = {
            'id': ['exact'],
            'user__email': ['exact'],
        }
        interfaces = (MembershipNodeInterface,)

```

**Query:**
```
QUERY_MEMBERSHIPS = '''
    query memberships($tenant: String!, $userEmail: String) {
        memberships(tenant: $tenant, user_Email: $userEmail) {
            edges {
                node {
                    id
                    isFitter
                    isMonitor
                    isAdmin
                    isStaff
                }
            }
        }
    }
'''
```

**Result:**
`Variable "userEmail" of type "String" used in position expecting type "ID".`




### Solution
Should be related to #750. Might be a special case due to the `email` being the identifying field of the `User`

> I am confident it is related to this PR: https://github.com/graphql-python/graphene-django/pull/682/files . In graphene_django/filter/utils.py the way how to retrieve the Type of a field was changed.

Keep on rocking :)



Discussion:
Damn, you fix one thing and another issue pops up! Any idea what is going wrong here @lassesteffen ?
Hey I updated the issue, something was not correctly saved by me. The actual issue is: `Variable "userEmail" of type "String" used in position expecting type "ID".`
I see why it's doing what it does. It is not coded to work with filtering on foreign keys, which is the problem here. Because the `user` field on Membership is indeed of type ID. But the problem is I am actually trying to filter by the `email` of the `User` model (which the `user` field is linking to.)  
The split in `line 21` in [utils.py](https://github.com/graphql-python/graphene-django/blob/master/graphene_django/filter/utils.py) breaks it, since it is written under the assumption that there are no accesses to foreign keys, and the `email` part of the `name` is just ignored. There should actually be some kind of loop to work with filtering on foreign keys.  
Or am I missing something?
@lassesteffen I'm seeing the same thing, but only when I have a single relation. As soon as I use two relations (as in `filter_fields = ['user__friend__email']`, for example) the type is appropriately inferred as a `String`.

I haven't had a chance to dive into the code or set up an example repo, but I can corroborate your findings at least partially.
@lassesteffen @curlywurlycraig sorry I haven't followed up on this. Have either of you got to a point where you could make a PR to fix this bug? (I'm pushed for time at the moment)
Looked at `utils.get_filtering_args_from_filterset` ; it does not recurse over foreign members when resolving field types. IE: this works: `user__email` , this does not: `user__friend__email`. The method looks at `user__friend__email` as filtering on a method `user__friend` which is not found thus falling back to what is provided as part of filterset_class.

Fortunately this is a common pattern and django-filter has implemented this as `utils.get_model_field(model, field_name)`: https://github.com/carltongibson/django-filter/blob/master/django_filters/utils.py#L130
I suggest we import and replace our logic.
That sounds good @zbyte64 . Do you have time to make a PR with the changes?

Resolving patch:
diff --git a/graphene_django/filter/utils.py b/graphene_django/filter/utils.py
--- a/graphene_django/filter/utils.py
+++ b/graphene_django/filter/utils.py
@@ -1,5 +1,6 @@
 import six
 
+from django_filters.utils import get_model_field
 from .filterset import custom_filterset_factory, setup_filterset
 
 
@@ -18,22 +19,12 @@ def get_filtering_args_from_filterset(filterset_class, type):
         if name in filterset_class.declared_filters:
             form_field = filter_field.field
         else:
-            try:
-                field_name, filter_type = name.rsplit("__", 1)
-            except ValueError:
-                field_name = name
-                filter_type = None
-
-            # If the filter type is `isnull` then use the filter provided by
-            # DjangoFilter (a BooleanFilter).
-            # Otherwise try and get a filter based on the actual model field
-            if filter_type != "isnull" and hasattr(model, field_name):
-                model_field = model._meta.get_field(field_name)
-
-                if hasattr(model_field, "formfield"):
-                    form_field = model_field.formfield(
-                        required=filter_field.extra.get("required", False)
-                    )
+            model_field = get_model_field(model, filter_field.field_name)
+            filter_type = filter_field.lookup_expr
+            if filter_type != "isnull" and hasattr(model_field, "formfield"):
+                form_field = model_field.formfield(
+                    required=filter_field.extra.get("required", False)
+                )
 
         # Fallback to field defined on filter if we can't get it from the
         # model field


Test patch: