Skip to content

Commit 34f617a

Browse files
committed
refactor convert_sqlalchemy_relationship
1 parent 108871d commit 34f617a

File tree

3 files changed

+63
-32
lines changed

3 files changed

+63
-32
lines changed

Diff for: graphene_sqlalchemy/converter.py

+55-23
Original file line numberDiff line numberDiff line change
@@ -34,47 +34,79 @@ def is_column_nullable(column):
3434

3535

3636
def convert_sqlalchemy_relationship(relationship_prop, obj_type, connection_field_factory, batching,
37-
attr_name, orm_field_name, **field_kwargs):
37+
orm_field_name, **field_kwargs):
3838
"""
3939
:param sqlalchemy.RelationshipProperty relationship_prop:
40-
:param Registry registry:
41-
:type function|None connection_field_factory:
42-
:type bool batching:
4340
:param SQLAlchemyObjectType obj_type:
41+
:param function|None connection_field_factory:
42+
:param bool batching:
4443
:param str orm_field_name:
44+
:param dict field_kwargs:
4545
:rtype: Dynamic
4646
"""
4747
def dynamic_type():
48+
""":rtype: Field|None"""
4849
direction = relationship_prop.direction
49-
model = relationship_prop.mapper.entity
50-
type_ = obj_type._meta.registry.get_type_for_model(model)
51-
50+
child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity)
5251
batching_ = batching if is_selectin_available else False
53-
connection_field_factory_ = connection_field_factory
5452

55-
if not type_:
53+
if not child_type:
5654
return None
5755

5856
if direction == interfaces.MANYTOONE or not relationship_prop.uselist:
59-
resolver = get_custom_resolver(obj_type, orm_field_name)
60-
if resolver is None:
61-
resolver = get_batch_resolver(relationship_prop) if batching_ else \
62-
get_attr_resolver(obj_type, relationship_prop.key)
63-
64-
return Field(type_, resolver=resolver, **field_kwargs)
57+
return _convert_o2o_or_m2o_relationship(relationship_prop, obj_type, batching_, orm_field_name,
58+
**field_kwargs)
6559

6660
if direction in (interfaces.ONETOMANY, interfaces.MANYTOMANY):
67-
if not type_._meta.connection:
68-
return Field(List(type_), **field_kwargs)
61+
return _convert_o2m_or_m2m_relationship(relationship_prop, obj_type, batching_,
62+
connection_field_factory, **field_kwargs)
63+
64+
return Dynamic(dynamic_type)
6965

70-
if connection_field_factory_ is None:
71-
connection_field_factory_ = BatchSQLAlchemyConnectionField.from_relationship if batching_ else \
72-
default_connection_field_factory
7366

74-
# TODO Allow override of connection_field_factory and resolver via ORMField
75-
return connection_field_factory_(relationship_prop, obj_type._meta.registry, **field_kwargs)
67+
def _convert_o2o_or_m2o_relationship(relationship_prop, obj_type, batching, orm_field_name, **field_kwargs):
68+
"""
69+
Convert one-to-one or many-to-one relationshsip. Return an object field.
7670
77-
return Dynamic(dynamic_type)
71+
:param sqlalchemy.RelationshipProperty relationship_prop:
72+
:param SQLAlchemyObjectType obj_type:
73+
:param bool batching:
74+
:param str orm_field_name:
75+
:param dict field_kwargs:
76+
:rtype: Field
77+
"""
78+
child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity)
79+
80+
resolver = get_custom_resolver(obj_type, orm_field_name)
81+
if resolver is None:
82+
resolver = get_batch_resolver(relationship_prop) if batching else \
83+
get_attr_resolver(obj_type, relationship_prop.key)
84+
85+
return Field(child_type, resolver=resolver, **field_kwargs)
86+
87+
88+
def _convert_o2m_or_m2m_relationship(relationship_prop, obj_type, batching, connection_field_factory, **field_kwargs):
89+
"""
90+
Convert one-to-many or many-to-many relationshsip. Return a list field or a connection field.
91+
92+
:param sqlalchemy.RelationshipProperty relationship_prop:
93+
:param SQLAlchemyObjectType obj_type:
94+
:param bool batching:
95+
:param function|None connection_field_factory:
96+
:param dict field_kwargs:
97+
:rtype: Field
98+
"""
99+
child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity)
100+
101+
if not child_type._meta.connection:
102+
return Field(List(child_type), **field_kwargs)
103+
104+
# TODO Allow override of connection_field_factory and resolver via ORMField
105+
if connection_field_factory is None:
106+
connection_field_factory = BatchSQLAlchemyConnectionField.from_relationship if batching else \
107+
default_connection_field_factory
108+
109+
return connection_field_factory(relationship_prop, obj_type._meta.registry, **field_kwargs)
78110

79111

80112
def convert_sqlalchemy_hybrid_method(hybrid_prop, resolver, **field_kwargs):

Diff for: graphene_sqlalchemy/tests/test_converter.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class Meta:
195195
model = Article
196196

197197
dynamic_field = convert_sqlalchemy_relationship(
198-
Reporter.pets.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
198+
Reporter.pets.property, A, default_connection_field_factory, True, 'orm_field_name',
199199
)
200200
assert isinstance(dynamic_field, graphene.Dynamic)
201201
assert not dynamic_field.get_type()
@@ -207,7 +207,7 @@ class Meta:
207207
model = Pet
208208

209209
dynamic_field = convert_sqlalchemy_relationship(
210-
Reporter.pets.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
210+
Reporter.pets.property, A, default_connection_field_factory, True, 'orm_field_name',
211211
)
212212
assert isinstance(dynamic_field, graphene.Dynamic)
213213
graphene_type = dynamic_field.get_type()
@@ -223,7 +223,7 @@ class Meta:
223223
interfaces = (Node,)
224224

225225
dynamic_field = convert_sqlalchemy_relationship(
226-
Reporter.pets.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
226+
Reporter.pets.property, A, default_connection_field_factory, True, 'orm_field_name',
227227
)
228228
assert isinstance(dynamic_field, graphene.Dynamic)
229229
assert isinstance(dynamic_field.get_type(), UnsortedSQLAlchemyConnectionField)
@@ -235,7 +235,7 @@ class Meta:
235235
model = Article
236236

237237
dynamic_field = convert_sqlalchemy_relationship(
238-
Reporter.pets.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
238+
Reporter.pets.property, A, default_connection_field_factory, True, 'orm_field_name',
239239
)
240240
assert isinstance(dynamic_field, graphene.Dynamic)
241241
assert not dynamic_field.get_type()
@@ -247,7 +247,7 @@ class Meta:
247247
model = Reporter
248248

249249
dynamic_field = convert_sqlalchemy_relationship(
250-
Article.reporter.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
250+
Article.reporter.property, A, default_connection_field_factory, True, 'orm_field_name',
251251
)
252252
assert isinstance(dynamic_field, graphene.Dynamic)
253253
graphene_type = dynamic_field.get_type()
@@ -262,7 +262,7 @@ class Meta:
262262
interfaces = (Node,)
263263

264264
dynamic_field = convert_sqlalchemy_relationship(
265-
Article.reporter.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
265+
Article.reporter.property, A, default_connection_field_factory, True, 'orm_field_name',
266266
)
267267
assert isinstance(dynamic_field, graphene.Dynamic)
268268
graphene_type = dynamic_field.get_type()
@@ -277,7 +277,7 @@ class Meta:
277277
interfaces = (Node,)
278278

279279
dynamic_field = convert_sqlalchemy_relationship(
280-
Reporter.favorite_article.property, A, default_connection_field_factory, True, 'attr_name', 'orm_field_name',
280+
Reporter.favorite_article.property, A, default_connection_field_factory, True, 'orm_field_name',
281281
)
282282
assert isinstance(dynamic_field, graphene.Dynamic)
283283
graphene_type = dynamic_field.get_type()

Diff for: graphene_sqlalchemy/types.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ def construct_fields(
162162
elif isinstance(attr, RelationshipProperty):
163163
batching_ = orm_field.kwargs.pop('batching', batching)
164164
field = convert_sqlalchemy_relationship(
165-
attr, obj_type, connection_field_factory, batching_, attr_name,
166-
orm_field_name, **orm_field.kwargs)
165+
attr, obj_type, connection_field_factory, batching_, orm_field_name, **orm_field.kwargs)
167166
elif isinstance(attr, CompositeProperty):
168167
if attr_name != orm_field_name or orm_field.kwargs:
169168
# TODO Add a way to override composite property fields

0 commit comments

Comments
 (0)