Skip to content

Commit eadd63d

Browse files
committed
Improved registry, raising only when constructing the schema.
1 parent 4a60da3 commit eadd63d

File tree

4 files changed

+46
-31
lines changed

4 files changed

+46
-31
lines changed

docs/registry.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ You retrieve using the function ``get_global_registry`` in
2525
model = ReporterModel
2626
2727
global_registry = get_global_registry
28-
global_registry.get_type_for_model(ReporterModel) # == Reporter
28+
global_registry.get_unique_type_for_model(ReporterModel) # == Reporter
2929
3030
3131
Multiple types for one model

graphene_django/converter.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def convert_onetoone_field_to_djangomodel(field, registry=None):
126126
model = get_related_model(field)
127127

128128
def dynamic_type():
129-
_type = registry.get_type_for_model(model)
129+
_type = registry.get_unique_type_for_model(model)
130130
if not _type:
131131
return
132132

@@ -145,7 +145,7 @@ def convert_field_to_list_or_connection(field, registry=None):
145145
model = get_related_model(field)
146146

147147
def dynamic_type():
148-
_type = registry.get_type_for_model(model)
148+
_type = registry.get_unique_type_for_model(model)
149149
if not _type:
150150
return
151151

@@ -163,7 +163,7 @@ def convert_relatedfield_to_djangomodel(field, registry=None):
163163
model = field.model
164164

165165
def dynamic_type():
166-
_type = registry.get_type_for_model(model)
166+
_type = registry.get_unique_type_for_model(model)
167167
if not _type:
168168
return
169169

@@ -183,7 +183,7 @@ def convert_field_to_djangomodel(field, registry=None):
183183
model = get_related_model(field)
184184

185185
def dynamic_type():
186-
_type = registry.get_type_for_model(model)
186+
_type = registry.get_unique_type_for_model(model)
187187
if not _type:
188188
return
189189

graphene_django/registry.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,40 @@
1+
from collections import defaultdict
2+
3+
14
class Registry(object):
25

36
def __init__(self):
4-
self._registry = {}
5-
self._registry_models = {}
7+
self._registry = defaultdict(list)
68

79
def register(self, cls):
810
from .types import DjangoObjectType
911
model = cls._meta.model
10-
assert self._registry.get(model, cls) == cls, (
11-
'Django Model "{}.{}" already associated with {}. '
12-
'You can use a different registry for {} or skip '
13-
'the global Registry with "{}.Meta.skip_global_registry = True".'
14-
).format(
15-
model._meta.app_label,
16-
model._meta.object_name,
17-
repr(self.get_type_for_model(cls._meta.model)),
18-
repr(cls),
19-
cls
20-
)
2112
assert issubclass(
2213
cls, DjangoObjectType), 'Only DjangoObjectTypes can be registered, received "{}"'.format(
2314
cls.__name__)
2415
assert cls._meta.registry == self, 'Registry for a Model have to match.'
25-
self._registry[cls._meta.model] = cls
16+
self._registry[model].append(cls)
17+
18+
def get_unique_type_for_model(self, model):
19+
types = self.get_types_for_model(model)
20+
if not types:
21+
return None
22+
23+
# If there is more than one type for the model, we should
24+
# raise an error so both types don't collide in the same schema.
25+
assert len(types) == 1, (
26+
'Found multiple ObjectTypes associated with the same Django Model "{}.{}": {}. '
27+
'You can use a different registry for each or skip '
28+
'the global Registry with Meta.skip_global_registry = True". '
29+
'Read more at http://docs.graphene-python.org/projects/django/en/latest/registry/ .'
30+
).format(
31+
model._meta.app_label,
32+
model._meta.object_name,
33+
repr(types),
34+
)
35+
return types[0]
2636

27-
def get_type_for_model(self, model):
37+
def get_types_for_model(self, model):
2838
return self._registry.get(model)
2939

3040

graphene_django/tests/test_registry.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,34 @@ class Meta:
1818
model = ReporterModel
1919

2020
assert Reporter._meta.registry == global_registry
21-
assert global_registry.get_type_for_model(ReporterModel) == Reporter
21+
assert global_registry.get_unique_type_for_model(ReporterModel) == Reporter
2222

2323

2424
def test_registry_multiple_types():
25+
global_registry = get_global_registry()
26+
2527
class Reporter(DjangoObjectType):
2628
'''Reporter description'''
2729
class Meta:
2830
model = ReporterModel
2931

30-
class Reporter2(object):
31-
pass
32+
class Reporter2(DjangoObjectType):
33+
'''Reporter2 description'''
34+
class Meta:
35+
model = ReporterModel
36+
37+
assert global_registry.get_types_for_model(ReporterModel) == [Reporter, Reporter2]
3238

3339
with raises(Exception) as exc_info:
34-
class Reporter2(DjangoObjectType):
35-
'''Reporter2 description'''
36-
class Meta:
37-
model = ReporterModel
40+
global_registry.get_unique_type_for_model(ReporterModel) == [Reporter, Reporter2]
3841

3942
assert str(exc_info.value) == (
40-
'Django Model "tests.Reporter" already associated with {}. '
41-
'You can use a different registry for {} '
42-
'or skip the global Registry with "Reporter2.Meta.skip_global_registry = True".'
43-
).format(repr(Reporter), repr(Reporter2))
43+
'Found multiple ObjectTypes associated with the same '
44+
'Django Model "tests.Reporter": {}. You can use a different '
45+
'registry for each or skip the global Registry with '
46+
'Meta.skip_global_registry = True". '
47+
'Read more at http://docs.graphene-python.org/projects/django/en/latest/registry/ .'
48+
).format(repr([Reporter, Reporter2]))
4449

4550

4651
def test_registry_multiple_types_dont_collision_if_skip_global_registry():

0 commit comments

Comments
 (0)