Skip to content

Commit a1aac36

Browse files
authored
Merge pull request #26 from graphql-python/feat-inheritance
Feature: Support model inheritance
2 parents 514db01 + d9163d0 commit a1aac36

File tree

7 files changed

+129
-15
lines changed

7 files changed

+129
-15
lines changed

graphene_mongo/tests/fixtures.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from .models import Article, Editor, EmbeddedArticle, Player, Reporter
1+
from .models import (
2+
Article, Editor, EmbeddedArticle, Player,
3+
Reporter, Parent, Child
4+
)
25

36

47
def setup_fixtures():
@@ -74,3 +77,10 @@ def setup_fixtures():
7477

7578
player2.players = [player1]
7679
player2.save()
80+
81+
Child.drop_collection()
82+
child1 = Child(bar='BAR', baz='BAZ')
83+
child1.save()
84+
85+
child2 = Child(bar='bar', baz='baz')
86+
child2.save()

graphene_mongo/tests/models.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class EmbeddedArticle(EmbeddedDocument):
4545

4646

4747
class Reporter(Document):
48-
meta = {'collection': 'test_repoter'}
4948

49+
meta = {'collection': 'test_repoter'}
5050
id = StringField(primary_key=True)
5151
first_name = StringField(required=True)
5252
last_name = StringField(required=True)
@@ -65,3 +65,18 @@ class Player(Document):
6565
articles = ListField(ReferenceField('Article'))
6666
embedded_list_articles = EmbeddedDocumentListField(EmbeddedArticle)
6767

68+
69+
class Parent(Document):
70+
71+
meta = {
72+
'collection': 'test_parent',
73+
'allow_inheritance': True
74+
}
75+
bar = StringField()
76+
77+
78+
class Child(Parent):
79+
80+
meta = {'collection': 'Child'}
81+
baz = StringField()
82+

graphene_mongo/tests/test_relay_query.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
from .types import (ArticleNode, ArticleType,
1010
EditorNode, EditorType,
1111
PlayerNode, PlayerType,
12-
ReporterNode, ReporterType)
12+
ReporterNode, ReporterType,
13+
ChildNode, ChildType)
1314
from ..fields import MongoengineConnectionField
1415

1516
setup_fixtures()
@@ -294,6 +295,43 @@ class Query(graphene.ObjectType):
294295
assert result.data == expected
295296

296297

298+
def test_should_filter_through_inheritance():
299+
300+
class Query(graphene.ObjectType):
301+
node = Node.Field()
302+
children = MongoengineConnectionField(ChildNode)
303+
304+
query = '''
305+
query ChildrenQuery {
306+
children(bar: "bar") {
307+
edges {
308+
node {
309+
bar,
310+
baz
311+
}
312+
}
313+
}
314+
}
315+
'''
316+
expected = {
317+
'children': {
318+
'edges': [
319+
{
320+
'node': {
321+
'bar': 'bar',
322+
'baz': 'baz',
323+
}
324+
}
325+
]
326+
}
327+
}
328+
schema = graphene.Schema(query=Query)
329+
result = schema.execute(query)
330+
assert not result.errors
331+
assert json.dumps(result.data, sort_keys=True) == json.dumps(
332+
expected, sort_keys=True)
333+
334+
297335
def test_should_get_node_by_id():
298336
# Notes: https://goo.gl/hMNRgs
299337
class Query(graphene.ObjectType):

graphene_mongo/tests/test_types.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
from .. import registry
77
from ..types import MongoengineObjectType
8-
from .models import Article
9-
from .models import Reporter
8+
from .models import Article, EmbeddedArticle, Reporter
9+
from .models import Parent, Child
1010
from .utils import with_local_registry
1111

1212
registry.reset_global_registry()
@@ -22,12 +22,33 @@ class Meta:
2222
interfaces = (Node,)
2323

2424

25+
class Being(MongoengineObjectType):
26+
27+
class Meta:
28+
model = EmbeddedArticle
29+
interfaces = (Node,)
30+
2531
class Character(MongoengineObjectType):
32+
2633
class Meta:
2734
model = Reporter
2835
registry = registry.get_global_registry()
2936

3037

38+
class Dad(MongoengineObjectType):
39+
40+
class Meta:
41+
model = Parent
42+
registry = registry.get_global_registry()
43+
44+
45+
class Son(MongoengineObjectType):
46+
47+
class Meta:
48+
model = Child
49+
registry = registry.get_global_registry()
50+
51+
3152
def test_mongoengine_interface():
3253
assert issubclass(Node, Interface)
3354
assert issubclass(Node, Node)
@@ -41,13 +62,16 @@ def test_objecttype_registered():
4162
'first_name',
4263
'last_name',
4364
'email',
44-
# FIXME
45-
# 'embedded_articles',
65+
'embedded_articles',
66+
'embedded_list_articles',
4667
'articles',
4768
'awards'
4869
])
4970

5071

72+
def test_mongoengine_inheritance():
73+
assert issubclass(Son._meta.model, Dad._meta.model)
74+
5175
def test_node_replacedfield():
5276
idfield = Human._meta.fields['pub_date']
5377
assert isinstance(idfield, Field)

graphene_mongo/tests/test_utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
from ..utils import (
66
get_model_fields, is_valid_mongoengine_model
77
)
8-
from .models import Reporter
8+
from .models import Reporter, Child
99

1010
def test_get_model_fields_no_duplication():
1111
reporter_fields = get_model_fields(Reporter)
1212
reporter_name_set = set(reporter_fields)
1313
assert len(reporter_fields) == len(reporter_name_set)
1414

1515

16+
def test_get_base_model_fields():
17+
child_fields = get_model_fields(Child)
18+
assert all(field in set(child_fields) for field in ['bar', 'baz'])
19+
1620
def test_is_valid_mongoengine_mode():
1721
assert is_valid_mongoengine_model(Reporter)
1822

graphene_mongo/tests/types.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from graphene.relay import Node
22

33
from ..types import MongoengineObjectType
4-
from .models import Article, Editor, EmbeddedArticle, Player, Reporter
4+
from .models import (
5+
Article, Editor, EmbeddedArticle, Player, Reporter,
6+
Parent, Child
7+
)
58

69

710
class EditorType(MongoengineObjectType):
@@ -34,6 +37,18 @@ class Meta:
3437
model = Reporter
3538

3639

40+
class ParentType(MongoengineObjectType):
41+
42+
class Meta:
43+
model = Parent
44+
45+
46+
class ChildType(MongoengineObjectType):
47+
48+
class Meta:
49+
model = Child
50+
51+
3752
class ArticleNode(MongoengineObjectType):
3853

3954
class Meta:
@@ -68,3 +83,15 @@ class Meta:
6883
model = Reporter
6984
interfaces = (Node,)
7085

86+
87+
class ParentNode(MongoengineObjectType):
88+
89+
class Meta:
90+
model = Parent
91+
interfaces = (Node,)
92+
93+
94+
class ChildNode(MongoengineObjectType):
95+
class Meta:
96+
model = Child
97+
interfaces = (Node,)

graphene_mongo/utils.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,16 @@
22
import mongoengine
33

44
from collections import OrderedDict
5-
from mongoengine.base.fields import BaseField
65

76

87
def get_model_fields(model, excluding=None):
98
if excluding is None:
109
excluding = []
1110
attributes = dict()
12-
for attr_name in vars(model):
11+
for attr_name, attr in model._fields.items():
1312
if attr_name in excluding:
1413
continue
15-
attr = getattr(model, attr_name)
16-
if isinstance(attr, BaseField):
17-
attributes[attr_name] = attr
18-
14+
attributes[attr_name] = attr
1915
return OrderedDict(sorted(attributes.items()))
2016

2117

0 commit comments

Comments
 (0)