mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-10-31 07:57:31 +03:00 
			
		
		
		
	Bugfix: Correct filter types for DjangoFilterConnectionFields (#682)
* Get form field from Django model before defaulting to django-filter * Add test * Cleanup some flake8 warnings and pytest warnings * Run isort and add black compatible config
This commit is contained in:
		
							parent
							
								
									9aabe2cbe6
								
							
						
					
					
						commit
						aa30750d39
					
				|  | @ -1,18 +1,17 @@ | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
|  | from textwrap import dedent | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  | from django.db.models import TextField, Value | ||||||
|  | from django.db.models.functions import Concat | ||||||
| 
 | 
 | ||||||
| from graphene import Field, ObjectType, Schema, Argument, Float, Boolean, String | from graphene import Argument, Boolean, Field, Float, ObjectType, Schema, String | ||||||
| from graphene.relay import Node | from graphene.relay import Node | ||||||
| from graphene_django import DjangoObjectType | from graphene_django import DjangoObjectType | ||||||
| from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField | from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField | ||||||
| from graphene_django.tests.models import Article, Pet, Reporter | from graphene_django.tests.models import Article, Pet, Reporter | ||||||
| from graphene_django.utils import DJANGO_FILTER_INSTALLED | from graphene_django.utils import DJANGO_FILTER_INSTALLED | ||||||
| 
 | 
 | ||||||
| # for annotation test |  | ||||||
| from django.db.models import TextField, Value |  | ||||||
| from django.db.models.functions import Concat |  | ||||||
| 
 |  | ||||||
| pytestmark = [] | pytestmark = [] | ||||||
| 
 | 
 | ||||||
| if DJANGO_FILTER_INSTALLED: | if DJANGO_FILTER_INSTALLED: | ||||||
|  | @ -183,7 +182,7 @@ def test_filter_shortcut_filterset_context(): | ||||||
|     } |     } | ||||||
|     """ |     """ | ||||||
|     schema = Schema(query=Query) |     schema = Schema(query=Query) | ||||||
|     result = schema.execute(query, context_value=context()) |     result = schema.execute(query, context=context()) | ||||||
|     assert not result.errors |     assert not result.errors | ||||||
| 
 | 
 | ||||||
|     assert len(result.data["contextArticles"]["edges"]) == 1 |     assert len(result.data["contextArticles"]["edges"]) == 1 | ||||||
|  | @ -462,15 +461,15 @@ def test_filter_filterset_related_results_with_filter(): | ||||||
|     class Query(ObjectType): |     class Query(ObjectType): | ||||||
|         all_reporters = DjangoFilterConnectionField(ReporterFilterNode) |         all_reporters = DjangoFilterConnectionField(ReporterFilterNode) | ||||||
| 
 | 
 | ||||||
|     r1 = Reporter.objects.create( |     Reporter.objects.create( | ||||||
|         first_name="A test user", last_name="Last Name", email="test1@test.com" |         first_name="A test user", last_name="Last Name", email="test1@test.com" | ||||||
|     ) |     ) | ||||||
|     r2 = Reporter.objects.create( |     Reporter.objects.create( | ||||||
|         first_name="Other test user", |         first_name="Other test user", | ||||||
|         last_name="Other Last Name", |         last_name="Other Last Name", | ||||||
|         email="test2@test.com", |         email="test2@test.com", | ||||||
|     ) |     ) | ||||||
|     r3 = Reporter.objects.create( |     Reporter.objects.create( | ||||||
|         first_name="Random", last_name="RandomLast", email="random@test.com" |         first_name="Random", last_name="RandomLast", email="random@test.com" | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | @ -638,7 +637,7 @@ def test_should_query_filter_node_double_limit_raises(): | ||||||
|     Reporter.objects.create( |     Reporter.objects.create( | ||||||
|         first_name="Bob", last_name="Doe", email="bobdoe@example.com", a_choice=2 |         first_name="Bob", last_name="Doe", email="bobdoe@example.com", a_choice=2 | ||||||
|     ) |     ) | ||||||
|     r = Reporter.objects.create( |     Reporter.objects.create( | ||||||
|         first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1 |         first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1 | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | @ -684,7 +683,7 @@ def test_order_by_is_perserved(): | ||||||
|             return reporters |             return reporters | ||||||
| 
 | 
 | ||||||
|     Reporter.objects.create(first_name="b") |     Reporter.objects.create(first_name="b") | ||||||
|     r = Reporter.objects.create(first_name="a") |     Reporter.objects.create(first_name="a") | ||||||
| 
 | 
 | ||||||
|     schema = Schema(query=Query) |     schema = Schema(query=Query) | ||||||
|     query = """ |     query = """ | ||||||
|  | @ -767,3 +766,55 @@ def test_annotation_is_perserved(): | ||||||
| 
 | 
 | ||||||
|     assert not result.errors |     assert not result.errors | ||||||
|     assert result.data == expected |     assert result.data == expected | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_integer_field_filter_type(): | ||||||
|  |     class PetType(DjangoObjectType): | ||||||
|  |         class Meta: | ||||||
|  |             model = Pet | ||||||
|  |             interfaces = (Node,) | ||||||
|  |             filter_fields = {"age": ["exact"]} | ||||||
|  |             only_fields = ["age"] | ||||||
|  | 
 | ||||||
|  |     class Query(ObjectType): | ||||||
|  |         pets = DjangoFilterConnectionField(PetType) | ||||||
|  | 
 | ||||||
|  |     schema = Schema(query=Query) | ||||||
|  | 
 | ||||||
|  |     assert str(schema) == dedent( | ||||||
|  |         """\ | ||||||
|  |         schema { | ||||||
|  |           query: Query | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         interface Node { | ||||||
|  |           id: ID! | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type PageInfo { | ||||||
|  |           hasNextPage: Boolean! | ||||||
|  |           hasPreviousPage: Boolean! | ||||||
|  |           startCursor: String | ||||||
|  |           endCursor: String | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type PetType implements Node { | ||||||
|  |           age: Int! | ||||||
|  |           id: ID! | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type PetTypeConnection { | ||||||
|  |           pageInfo: PageInfo! | ||||||
|  |           edges: [PetTypeEdge]! | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type PetTypeEdge { | ||||||
|  |           node: PetType | ||||||
|  |           cursor: String! | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         type Query { | ||||||
|  |           pets(before: String, after: String, first: Int, last: Int, age: Int): PetTypeConnection | ||||||
|  |         } | ||||||
|  |     """ | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  | @ -11,8 +11,25 @@ def get_filtering_args_from_filterset(filterset_class, type): | ||||||
|     from ..forms.converter import convert_form_field |     from ..forms.converter import convert_form_field | ||||||
| 
 | 
 | ||||||
|     args = {} |     args = {} | ||||||
|  |     model = filterset_class._meta.model | ||||||
|     for name, filter_field in six.iteritems(filterset_class.base_filters): |     for name, filter_field in six.iteritems(filterset_class.base_filters): | ||||||
|         field_type = convert_form_field(filter_field.field).Argument() |         if name in filterset_class.declared_filters: | ||||||
|  |             form_field = filter_field.field | ||||||
|  |         else: | ||||||
|  |             field_name = name.split("__", 1)[0] | ||||||
|  |             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) | ||||||
|  |                 ) | ||||||
|  | 
 | ||||||
|  |             # Fallback to field defined on filter if we can't get it from the | ||||||
|  |             # model field | ||||||
|  |             if not form_field: | ||||||
|  |                 form_field = filter_field.field | ||||||
|  | 
 | ||||||
|  |         field_type = convert_form_field(form_field).Argument() | ||||||
|         field_type.description = filter_field.label |         field_type.description = filter_field.label | ||||||
|         args[name] = field_type |         args[name] = field_type | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user