Skip to content

Commit 4e1b82a

Browse files
authored
Check exclude fields correctly (#873)
1 parent bbf119c commit 4e1b82a

File tree

2 files changed

+83
-21
lines changed

2 files changed

+83
-21
lines changed

graphene_django/tests/test_types.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class Meta:
319319

320320

321321
@with_local_registry
322-
def test_django_objecttype_fields_exclude_exist_on_model():
322+
def test_django_objecttype_fields_exist_on_model():
323323
with pytest.warns(UserWarning, match=r"Field name .* doesn't exist"):
324324

325325
class Reporter(DjangoObjectType):
@@ -350,6 +350,42 @@ class Meta:
350350
assert len(record) == 0
351351

352352

353+
@with_local_registry
354+
def test_django_objecttype_exclude_fields_exist_on_model():
355+
with pytest.warns(
356+
UserWarning,
357+
match=r"Django model .* does not have a field or attribute named .*",
358+
):
359+
360+
class Reporter(DjangoObjectType):
361+
class Meta:
362+
model = ReporterModel
363+
exclude = ["foo"]
364+
365+
# Don't warn if selecting a custom field
366+
with pytest.warns(
367+
UserWarning,
368+
match=r"Excluding the custom field .* on DjangoObjectType .* has no effect.",
369+
):
370+
371+
class Reporter3(DjangoObjectType):
372+
custom_field = String()
373+
374+
class Meta:
375+
model = ReporterModel
376+
exclude = ["custom_field"]
377+
378+
# Don't warn on exclude fields
379+
with pytest.warns(None) as record:
380+
381+
class Reporter4(DjangoObjectType):
382+
class Meta:
383+
model = ReporterModel
384+
exclude = ["email", "first_name"]
385+
386+
assert len(record) == 0
387+
388+
353389
class TestDjangoObjectType:
354390
@pytest.fixture
355391
def PetModel(self):

graphene_django/types.py

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,58 @@ def construct_fields(
6565
def validate_fields(type_, model, fields, only_fields, exclude_fields):
6666
# Validate the given fields against the model's fields and custom fields
6767
all_field_names = set(fields.keys())
68-
for fields_list in (only_fields, exclude_fields):
69-
if not fields_list:
68+
for name in only_fields or ():
69+
if name in all_field_names:
7070
continue
71-
for name in fields_list:
72-
if name in all_field_names:
73-
continue
7471

75-
if hasattr(model, name):
76-
warnings.warn(
77-
(
78-
'Field name "{field_name}" matches an attribute on Django model "{app_label}.{object_name}" '
79-
"but it's not a model field so Graphene cannot determine what type it should be. "
80-
'Either define the type of the field on DjangoObjectType "{type_}" or remove it from the "fields" list.'
81-
).format(
82-
field_name=name,
83-
app_label=model._meta.app_label,
84-
object_name=model._meta.object_name,
85-
type_=type_,
86-
)
72+
if hasattr(model, name):
73+
warnings.warn(
74+
(
75+
'Field name "{field_name}" matches an attribute on Django model "{app_label}.{object_name}" '
76+
"but it's not a model field so Graphene cannot determine what type it should be. "
77+
'Either define the type of the field on DjangoObjectType "{type_}" or remove it from the "fields" list.'
78+
).format(
79+
field_name=name,
80+
app_label=model._meta.app_label,
81+
object_name=model._meta.object_name,
82+
type_=type_,
8783
)
84+
)
8885

89-
else:
86+
else:
87+
warnings.warn(
88+
(
89+
'Field name "{field_name}" doesn\'t exist on Django model "{app_label}.{object_name}". '
90+
'Consider removing the field from the "fields" list of DjangoObjectType "{type_}" because it has no effect.'
91+
).format(
92+
field_name=name,
93+
app_label=model._meta.app_label,
94+
object_name=model._meta.object_name,
95+
type_=type_,
96+
)
97+
)
98+
99+
# Validate exclude fields
100+
for name in exclude_fields or ():
101+
if name in all_field_names:
102+
# Field is a custom field
103+
warnings.warn(
104+
(
105+
'Excluding the custom field "{field_name} on DjangoObjectType "{type_}" has no effect. '
106+
'Either remove the custom field or remove the field from the "exclude" list.'
107+
).format(
108+
field_name=name,
109+
app_label=model._meta.app_label,
110+
object_name=model._meta.object_name,
111+
type_=type_,
112+
)
113+
)
114+
else:
115+
if not hasattr(model, name):
90116
warnings.warn(
91117
(
92-
'Field name "{field_name}" doesn\'t exist on Django model "{app_label}.{object_name}". '
93-
'Consider removing the field from the "fields" list of DjangoObjectType "{type_}" because it has no effect.'
118+
'Django model "{app_label}.{object_name}" does not have a field or attribute named "{field_name}". '
119+
'Consider removing the field from the "exclude" list of DjangoObjectType "{type_}" because it has no effect'
94120
).format(
95121
field_name=name,
96122
app_label=model._meta.app_label,

0 commit comments

Comments
 (0)