mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-25 19:14:11 +03:00
Merge pull request #603 from abettke/fix/enhanced-proxy-model-support
Adds enhanced support for proxy models.
This commit is contained in:
commit
b271b259bd
|
@ -65,6 +65,11 @@ class Reporter(models.Model):
|
|||
self.__class__ = CNNReporter
|
||||
|
||||
|
||||
class CNNReporterManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return super(CNNReporterManager, self).get_queryset().filter(reporter_type=2)
|
||||
|
||||
|
||||
class CNNReporter(Reporter):
|
||||
"""
|
||||
This class is a proxy model for Reporter, used for testing
|
||||
|
@ -74,6 +79,8 @@ class CNNReporter(Reporter):
|
|||
class Meta:
|
||||
proxy = True
|
||||
|
||||
objects = CNNReporterManager()
|
||||
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(max_length=100)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import base64
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
@ -7,6 +8,7 @@ from py.test import raises
|
|||
|
||||
from django.db.models import Q
|
||||
|
||||
from graphql_relay import to_global_id
|
||||
import graphene
|
||||
from graphene.relay import Node
|
||||
|
||||
|
@ -951,8 +953,7 @@ def test_should_handle_inherited_choices():
|
|||
|
||||
def test_proxy_model_support():
|
||||
"""
|
||||
This test asserts that we can query for all Reporters,
|
||||
even if some are of a proxy model type at runtime.
|
||||
This test asserts that we can query for all Reporters and proxied Reporters.
|
||||
"""
|
||||
|
||||
class ReporterType(DjangoObjectType):
|
||||
|
@ -961,11 +962,17 @@ def test_proxy_model_support():
|
|||
interfaces = (Node,)
|
||||
use_connection = True
|
||||
|
||||
reporter_1 = Reporter.objects.create(
|
||||
class CNNReporterType(DjangoObjectType):
|
||||
class Meta:
|
||||
model = CNNReporter
|
||||
interfaces = (Node,)
|
||||
use_connection = True
|
||||
|
||||
reporter = Reporter.objects.create(
|
||||
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
|
||||
)
|
||||
|
||||
reporter_2 = CNNReporter.objects.create(
|
||||
cnn_reporter = CNNReporter.objects.create(
|
||||
first_name="Some",
|
||||
last_name="Guy",
|
||||
email="someguy@cnn.com",
|
||||
|
@ -975,6 +982,7 @@ def test_proxy_model_support():
|
|||
|
||||
class Query(graphene.ObjectType):
|
||||
all_reporters = DjangoConnectionField(ReporterType)
|
||||
cnn_reporters = DjangoConnectionField(CNNReporterType)
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
query = """
|
||||
|
@ -986,14 +994,26 @@ def test_proxy_model_support():
|
|||
}
|
||||
}
|
||||
}
|
||||
cnnReporters {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
expected = {
|
||||
"allReporters": {
|
||||
"edges": [
|
||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
|
||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
|
||||
{"node": {"id": to_global_id("ReporterType", reporter.id)}},
|
||||
{"node": {"id": to_global_id("ReporterType", cnn_reporter.id)}},
|
||||
]
|
||||
},
|
||||
"cnnReporters": {
|
||||
"edges": [
|
||||
{"node": {"id": to_global_id("CNNReporterType", cnn_reporter.id)}}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1001,69 +1021,7 @@ def test_proxy_model_support():
|
|||
result = schema.execute(query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
||||
def test_proxy_model_fails():
|
||||
"""
|
||||
This test asserts that if you try to query for a proxy model,
|
||||
that query will fail with:
|
||||
GraphQLError('Expected value of type "CNNReporterType" but got:
|
||||
CNNReporter.',)
|
||||
|
||||
This is because a proxy model has the identical model definition
|
||||
to its superclass, and defines its behavior at runtime, rather than
|
||||
at the database level. Currently, filtering objects of the proxy models'
|
||||
type isn't supported. It would require a field on the model that would
|
||||
represent the type, and it doesn't seem like there is a clear way to
|
||||
enforce this pattern across all projects
|
||||
"""
|
||||
|
||||
class CNNReporterType(DjangoObjectType):
|
||||
class Meta:
|
||||
model = CNNReporter
|
||||
interfaces = (Node,)
|
||||
use_connection = True
|
||||
|
||||
reporter_1 = Reporter.objects.create(
|
||||
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
|
||||
)
|
||||
|
||||
reporter_2 = CNNReporter.objects.create(
|
||||
first_name="Some",
|
||||
last_name="Guy",
|
||||
email="someguy@cnn.com",
|
||||
a_choice=1,
|
||||
reporter_type=2, # set this guy to be CNN
|
||||
)
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
all_reporters = DjangoConnectionField(CNNReporterType)
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
query = """
|
||||
query ProxyModelQuery {
|
||||
allReporters {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
expected = {
|
||||
"allReporters": {
|
||||
"edges": [
|
||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
|
||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
result = schema.execute(query)
|
||||
assert result.errors
|
||||
|
||||
|
||||
|
||||
def test_should_resolve_get_queryset_connectionfields():
|
||||
reporter_1 = Reporter.objects.create(
|
||||
|
|
|
@ -131,7 +131,11 @@ class DjangoObjectType(ObjectType):
|
|||
if not is_valid_django_model(type(root)):
|
||||
raise Exception(('Received incompatible instance "{}".').format(root))
|
||||
|
||||
model = root._meta.model._meta.concrete_model
|
||||
if cls._meta.model._meta.proxy:
|
||||
model = root._meta.model
|
||||
else:
|
||||
model = root._meta.model._meta.concrete_model
|
||||
|
||||
return model == cls._meta.model
|
||||
|
||||
@classmethod
|
||||
|
|
Loading…
Reference in New Issue
Block a user