Skip to content

Commit b271b25

Browse files
authored
Merge pull request #603 from abettke/fix/enhanced-proxy-model-support
Adds enhanced support for proxy models.
2 parents 83cc0d7 + a7ee042 commit b271b25

File tree

3 files changed

+35
-66
lines changed

3 files changed

+35
-66
lines changed

graphene_django/tests/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ def __init__(self, *args, **kwargs):
6565
self.__class__ = CNNReporter
6666

6767

68+
class CNNReporterManager(models.Manager):
69+
def get_queryset(self):
70+
return super(CNNReporterManager, self).get_queryset().filter(reporter_type=2)
71+
72+
6873
class CNNReporter(Reporter):
6974
"""
7075
This class is a proxy model for Reporter, used for testing
@@ -74,6 +79,8 @@ class CNNReporter(Reporter):
7479
class Meta:
7580
proxy = True
7681

82+
objects = CNNReporterManager()
83+
7784

7885
class Article(models.Model):
7986
headline = models.CharField(max_length=100)

graphene_django/tests/test_query.py

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
import datetime
23

34
import pytest
@@ -7,6 +8,7 @@
78

89
from django.db.models import Q
910

11+
from graphql_relay import to_global_id
1012
import graphene
1113
from graphene.relay import Node
1214

@@ -951,8 +953,7 @@ class Query(graphene.ObjectType):
951953

952954
def test_proxy_model_support():
953955
"""
954-
This test asserts that we can query for all Reporters,
955-
even if some are of a proxy model type at runtime.
956+
This test asserts that we can query for all Reporters and proxied Reporters.
956957
"""
957958

958959
class ReporterType(DjangoObjectType):
@@ -961,11 +962,17 @@ class Meta:
961962
interfaces = (Node,)
962963
use_connection = True
963964

964-
reporter_1 = Reporter.objects.create(
965+
class CNNReporterType(DjangoObjectType):
966+
class Meta:
967+
model = CNNReporter
968+
interfaces = (Node,)
969+
use_connection = True
970+
971+
reporter = Reporter.objects.create(
965972
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
966973
)
967974

968-
reporter_2 = CNNReporter.objects.create(
975+
cnn_reporter = CNNReporter.objects.create(
969976
first_name="Some",
970977
last_name="Guy",
971978
email="someguy@cnn.com",
@@ -975,6 +982,7 @@ class Meta:
975982

976983
class Query(graphene.ObjectType):
977984
all_reporters = DjangoConnectionField(ReporterType)
985+
cnn_reporters = DjangoConnectionField(CNNReporterType)
978986

979987
schema = graphene.Schema(query=Query)
980988
query = """
@@ -986,63 +994,7 @@ class Query(graphene.ObjectType):
986994
}
987995
}
988996
}
989-
}
990-
"""
991-
992-
expected = {
993-
"allReporters": {
994-
"edges": [
995-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
996-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
997-
]
998-
}
999-
}
1000-
1001-
result = schema.execute(query)
1002-
assert not result.errors
1003-
assert result.data == expected
1004-
1005-
1006-
def test_proxy_model_fails():
1007-
"""
1008-
This test asserts that if you try to query for a proxy model,
1009-
that query will fail with:
1010-
GraphQLError('Expected value of type "CNNReporterType" but got:
1011-
CNNReporter.',)
1012-
1013-
This is because a proxy model has the identical model definition
1014-
to its superclass, and defines its behavior at runtime, rather than
1015-
at the database level. Currently, filtering objects of the proxy models'
1016-
type isn't supported. It would require a field on the model that would
1017-
represent the type, and it doesn't seem like there is a clear way to
1018-
enforce this pattern across all projects
1019-
"""
1020-
1021-
class CNNReporterType(DjangoObjectType):
1022-
class Meta:
1023-
model = CNNReporter
1024-
interfaces = (Node,)
1025-
use_connection = True
1026-
1027-
reporter_1 = Reporter.objects.create(
1028-
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
1029-
)
1030-
1031-
reporter_2 = CNNReporter.objects.create(
1032-
first_name="Some",
1033-
last_name="Guy",
1034-
email="someguy@cnn.com",
1035-
a_choice=1,
1036-
reporter_type=2, # set this guy to be CNN
1037-
)
1038-
1039-
class Query(graphene.ObjectType):
1040-
all_reporters = DjangoConnectionField(CNNReporterType)
1041-
1042-
schema = graphene.Schema(query=Query)
1043-
query = """
1044-
query ProxyModelQuery {
1045-
allReporters {
997+
cnnReporters {
1046998
edges {
1047999
node {
10481000
id
@@ -1055,15 +1007,21 @@ class Query(graphene.ObjectType):
10551007
expected = {
10561008
"allReporters": {
10571009
"edges": [
1058-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
1059-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
1010+
{"node": {"id": to_global_id("ReporterType", reporter.id)}},
1011+
{"node": {"id": to_global_id("ReporterType", cnn_reporter.id)}},
1012+
]
1013+
},
1014+
"cnnReporters": {
1015+
"edges": [
1016+
{"node": {"id": to_global_id("CNNReporterType", cnn_reporter.id)}}
10601017
]
10611018
}
10621019
}
10631020

10641021
result = schema.execute(query)
1065-
assert result.errors
1066-
1022+
assert not result.errors
1023+
assert result.data == expected
1024+
10671025

10681026
def test_should_resolve_get_queryset_connectionfields():
10691027
reporter_1 = Reporter.objects.create(

graphene_django/types.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ def is_type_of(cls, root, info):
131131
if not is_valid_django_model(type(root)):
132132
raise Exception(('Received incompatible instance "{}".').format(root))
133133

134-
model = root._meta.model._meta.concrete_model
134+
if cls._meta.model._meta.proxy:
135+
model = root._meta.model
136+
else:
137+
model = root._meta.model._meta.concrete_model
138+
135139
return model == cls._meta.model
136140

137141
@classmethod

0 commit comments

Comments
 (0)