Skip to content

Commit 36ac562

Browse files
author
Andrew Bettke
committed
Adds enhanced support for proxy models.
1 parent ea2cd98 commit 36ac562

File tree

3 files changed

+33
-65
lines changed

3 files changed

+33
-65
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: 21 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
import datetime
23

34
import pytest
@@ -895,8 +896,7 @@ class Query(graphene.ObjectType):
895896

896897
def test_proxy_model_support():
897898
"""
898-
This test asserts that we can query for all Reporters,
899-
even if some are of a proxy model type at runtime.
899+
This test asserts that we can query for all Reporters and proxied Reporters.
900900
"""
901901

902902
class ReporterType(DjangoObjectType):
@@ -905,11 +905,17 @@ class Meta:
905905
interfaces = (Node,)
906906
use_connection = True
907907

908-
reporter_1 = Reporter.objects.create(
908+
class CNNReporterType(DjangoObjectType):
909+
class Meta:
910+
model = CNNReporter
911+
interfaces = (Node,)
912+
use_connection = True
913+
914+
reporter = Reporter.objects.create(
909915
first_name="John", last_name="Doe", email="[email protected]", a_choice=1
910916
)
911917

912-
reporter_2 = CNNReporter.objects.create(
918+
cnn_reporter = CNNReporter.objects.create(
913919
first_name="Some",
914920
last_name="Guy",
915921
@@ -919,6 +925,7 @@ class Meta:
919925

920926
class Query(graphene.ObjectType):
921927
all_reporters = DjangoConnectionField(ReporterType)
928+
cnn_reporters = DjangoConnectionField(CNNReporterType)
922929

923930
schema = graphene.Schema(query=Query)
924931
query = """
@@ -930,63 +937,7 @@ class Query(graphene.ObjectType):
930937
}
931938
}
932939
}
933-
}
934-
"""
935-
936-
expected = {
937-
"allReporters": {
938-
"edges": [
939-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
940-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
941-
]
942-
}
943-
}
944-
945-
result = schema.execute(query)
946-
assert not result.errors
947-
assert result.data == expected
948-
949-
950-
def test_proxy_model_fails():
951-
"""
952-
This test asserts that if you try to query for a proxy model,
953-
that query will fail with:
954-
GraphQLError('Expected value of type "CNNReporterType" but got:
955-
CNNReporter.',)
956-
957-
This is because a proxy model has the identical model definition
958-
to its superclass, and defines its behavior at runtime, rather than
959-
at the database level. Currently, filtering objects of the proxy models'
960-
type isn't supported. It would require a field on the model that would
961-
represent the type, and it doesn't seem like there is a clear way to
962-
enforce this pattern across all projects
963-
"""
964-
965-
class CNNReporterType(DjangoObjectType):
966-
class Meta:
967-
model = CNNReporter
968-
interfaces = (Node,)
969-
use_connection = True
970-
971-
reporter_1 = Reporter.objects.create(
972-
first_name="John", last_name="Doe", email="[email protected]", a_choice=1
973-
)
974-
975-
reporter_2 = CNNReporter.objects.create(
976-
first_name="Some",
977-
last_name="Guy",
978-
979-
a_choice=1,
980-
reporter_type=2, # set this guy to be CNN
981-
)
982-
983-
class Query(graphene.ObjectType):
984-
all_reporters = DjangoConnectionField(CNNReporterType)
985-
986-
schema = graphene.Schema(query=Query)
987-
query = """
988-
query ProxyModelQuery {
989-
allReporters {
940+
cnnReporters {
990941
edges {
991942
node {
992943
id
@@ -999,11 +950,17 @@ class Query(graphene.ObjectType):
999950
expected = {
1000951
"allReporters": {
1001952
"edges": [
1002-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
1003-
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
953+
{"node": {"id": base64.b64encode("ReporterType:{}".format(reporter.id))}},
954+
{"node": {"id": base64.b64encode("ReporterType:{}".format(cnn_reporter.id))}},
955+
]
956+
},
957+
"cnnReporters": {
958+
"edges": [
959+
{"node": {"id": base64.b64encode("CNNReporterType:{}".format(cnn_reporter.id))}}
1004960
]
1005961
}
1006962
}
1007963

1008964
result = schema.execute(query)
1009-
assert result.errors
965+
assert not result.errors
966+
assert result.data == expected

graphene_django/types.py

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

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

136140
@classmethod

0 commit comments

Comments
 (0)