mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-29 13:03:44 +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
|
self.__class__ = CNNReporter
|
||||||
|
|
||||||
|
|
||||||
|
class CNNReporterManager(models.Manager):
|
||||||
|
def get_queryset(self):
|
||||||
|
return super(CNNReporterManager, self).get_queryset().filter(reporter_type=2)
|
||||||
|
|
||||||
|
|
||||||
class CNNReporter(Reporter):
|
class CNNReporter(Reporter):
|
||||||
"""
|
"""
|
||||||
This class is a proxy model for Reporter, used for testing
|
This class is a proxy model for Reporter, used for testing
|
||||||
|
@ -74,6 +79,8 @@ class CNNReporter(Reporter):
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
|
objects = CNNReporterManager()
|
||||||
|
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
headline = models.CharField(max_length=100)
|
headline = models.CharField(max_length=100)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -7,6 +8,7 @@ from py.test import raises
|
||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from graphql_relay import to_global_id
|
||||||
import graphene
|
import graphene
|
||||||
from graphene.relay import Node
|
from graphene.relay import Node
|
||||||
|
|
||||||
|
@ -951,8 +953,7 @@ def test_should_handle_inherited_choices():
|
||||||
|
|
||||||
def test_proxy_model_support():
|
def test_proxy_model_support():
|
||||||
"""
|
"""
|
||||||
This test asserts that we can query for all Reporters,
|
This test asserts that we can query for all Reporters and proxied Reporters.
|
||||||
even if some are of a proxy model type at runtime.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class ReporterType(DjangoObjectType):
|
class ReporterType(DjangoObjectType):
|
||||||
|
@ -961,11 +962,17 @@ def test_proxy_model_support():
|
||||||
interfaces = (Node,)
|
interfaces = (Node,)
|
||||||
use_connection = True
|
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
|
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",
|
first_name="Some",
|
||||||
last_name="Guy",
|
last_name="Guy",
|
||||||
email="someguy@cnn.com",
|
email="someguy@cnn.com",
|
||||||
|
@ -975,6 +982,7 @@ def test_proxy_model_support():
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(graphene.ObjectType):
|
||||||
all_reporters = DjangoConnectionField(ReporterType)
|
all_reporters = DjangoConnectionField(ReporterType)
|
||||||
|
cnn_reporters = DjangoConnectionField(CNNReporterType)
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query)
|
schema = graphene.Schema(query=Query)
|
||||||
query = """
|
query = """
|
||||||
|
@ -986,14 +994,26 @@ def test_proxy_model_support():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cnnReporters {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
"allReporters": {
|
"allReporters": {
|
||||||
"edges": [
|
"edges": [
|
||||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjE="}},
|
{"node": {"id": to_global_id("ReporterType", reporter.id)}},
|
||||||
{"node": {"id": "UmVwb3J0ZXJUeXBlOjI="}},
|
{"node": {"id": to_global_id("ReporterType", cnn_reporter.id)}},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cnnReporters": {
|
||||||
|
"edges": [
|
||||||
|
{"node": {"id": to_global_id("CNNReporterType", cnn_reporter.id)}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,68 +1023,6 @@ def test_proxy_model_support():
|
||||||
assert result.data == expected
|
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():
|
def test_should_resolve_get_queryset_connectionfields():
|
||||||
reporter_1 = Reporter.objects.create(
|
reporter_1 = 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
|
||||||
|
|
|
@ -131,7 +131,11 @@ class DjangoObjectType(ObjectType):
|
||||||
if not is_valid_django_model(type(root)):
|
if not is_valid_django_model(type(root)):
|
||||||
raise Exception(('Received incompatible instance "{}".').format(root))
|
raise Exception(('Received incompatible instance "{}".').format(root))
|
||||||
|
|
||||||
|
if cls._meta.model._meta.proxy:
|
||||||
|
model = root._meta.model
|
||||||
|
else:
|
||||||
model = root._meta.model._meta.concrete_model
|
model = root._meta.model._meta.concrete_model
|
||||||
|
|
||||||
return model == cls._meta.model
|
return model == cls._meta.model
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
Loading…
Reference in New Issue
Block a user