Skip to content

Commit 365a0ec

Browse files
committed
Add SQLAlchemyList and SQLAlchemyMutation types
This brings default support for fields filtering and ordering on queries and mutations.
1 parent ecd9a91 commit 365a0ec

File tree

5 files changed

+500
-24
lines changed

5 files changed

+500
-24
lines changed

graphene_sqlalchemy/mutations.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from graphene_sqlalchemy.types import SQLAlchemyMutation
2+
3+
4+
def create(of_type):
5+
class CreateModel(SQLAlchemyMutation):
6+
class Meta:
7+
model = of_type._meta.model
8+
create = True
9+
Output = of_type
10+
return CreateModel.Field()
11+
12+
13+
def update(of_type):
14+
class UpdateModel(SQLAlchemyMutation):
15+
class Meta:
16+
model = of_type._meta.model
17+
Output = of_type
18+
return UpdateModel.Field()
19+
20+
21+
def delete(of_type):
22+
class DeleteModel(SQLAlchemyMutation):
23+
class Meta:
24+
model = of_type._meta.model
25+
delete = True
26+
Output = of_type
27+
return DeleteModel.Field()

graphene_sqlalchemy/tests/test_query.py

+246-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from ..registry import reset_global_registry
99
from ..fields import SQLAlchemyConnectionField
10-
from ..types import SQLAlchemyObjectType
10+
from ..types import SQLAlchemyObjectType, SQLAlchemyList
1111
from .models import Article, Base, Editor, Reporter
1212

1313
db = create_engine('sqlite:///test_sqlalchemy.sqlite3')
@@ -45,11 +45,10 @@ def setup_fixtures(session):
4545
session.commit()
4646

4747

48-
def test_should_query_well(session):
48+
def test_should_query_well_with_graphene_types(session):
4949
setup_fixtures(session)
5050

5151
class ReporterType(SQLAlchemyObjectType):
52-
5352
class Meta:
5453
model = Reporter
5554

@@ -93,24 +92,257 @@ def resolve_reporters(self, *args, **kwargs):
9392
assert result.data == expected
9493

9594

95+
def test_should_filter_with_sqlalchemy_fields(session):
96+
setup_fixtures(session)
97+
98+
class ReporterType(SQLAlchemyObjectType):
99+
class Meta:
100+
model = Reporter
101+
102+
class Query(graphene.ObjectType):
103+
reporters = SQLAlchemyList(ReporterType)
104+
105+
query = '''
106+
query ReporterQuery {
107+
reporters(firstName: "ABA") {
108+
firstName,
109+
lastName,
110+
email
111+
}
112+
}
113+
'''
114+
expected = {
115+
'reporters': [{
116+
'firstName': 'ABA',
117+
'lastName': 'X',
118+
'email': None
119+
}]
120+
}
121+
schema = graphene.Schema(query=Query)
122+
result = schema.execute(query, context_value={'session': session})
123+
assert not result.errors
124+
assert result.data == expected
125+
126+
127+
def test_should_filter_with_custom_argument(session):
128+
setup_fixtures(session)
129+
130+
class ReporterType(SQLAlchemyObjectType):
131+
class Meta:
132+
model = Reporter
133+
134+
class Query(graphene.ObjectType):
135+
reporters = SQLAlchemyList(ReporterType, contains_o=graphene.Boolean())
136+
137+
def query_reporters(self, info, query, **kwargs):
138+
return query.filter(Reporter.first_name.contains('O') == kwargs['contains_o'])
139+
140+
query = '''
141+
query ReporterQuery {
142+
reporters(lastName: "Y", containsO: true) {
143+
firstName,
144+
lastName,
145+
email
146+
}
147+
}
148+
'''
149+
expected = {
150+
'reporters': [{
151+
'firstName': 'ABO',
152+
'lastName': 'Y',
153+
'email': None
154+
}]
155+
}
156+
schema = graphene.Schema(query=Query)
157+
result = schema.execute(query, context_value={'session': session})
158+
assert not result.errors
159+
assert result.data == expected
160+
161+
query = '''
162+
query ReporterQuery {
163+
reporters(containsO: false) {
164+
firstName,
165+
lastName,
166+
email
167+
}
168+
}
169+
'''
170+
expected = {
171+
'reporters': [{
172+
'firstName': 'ABA',
173+
'lastName': 'X',
174+
'email': None
175+
}]
176+
}
177+
schema = graphene.Schema(query=Query)
178+
result = schema.execute(query, context_value={'session': session})
179+
assert not result.errors
180+
assert result.data == expected
181+
182+
183+
def test_should_filter_with_custom_operator(session):
184+
setup_fixtures(session)
185+
186+
class ReporterType(SQLAlchemyObjectType):
187+
class Meta:
188+
model = Reporter
189+
190+
class Query(graphene.ObjectType):
191+
reporters = SQLAlchemyList(ReporterType, operator='like')
192+
193+
query = '''
194+
query ReporterQuery {
195+
reporters(firstName: "%BO%") {
196+
firstName,
197+
lastName,
198+
email
199+
}
200+
}
201+
'''
202+
expected = {
203+
'reporters': [{
204+
'firstName': 'ABO',
205+
'lastName': 'Y',
206+
'email': None
207+
}]
208+
}
209+
schema = graphene.Schema(query=Query)
210+
result = schema.execute(query, context_value={'session': session})
211+
assert not result.errors
212+
assert result.data == expected
213+
214+
215+
def test_should_order_by(session):
216+
setup_fixtures(session)
217+
218+
class ReporterType(SQLAlchemyObjectType):
219+
class Meta:
220+
model = Reporter
221+
222+
class Query(graphene.ObjectType):
223+
reporters = SQLAlchemyList(ReporterType, order_by='firstName')
224+
225+
query = '''
226+
query ReporterQuery {
227+
reporters {
228+
firstName,
229+
lastName,
230+
email
231+
}
232+
}
233+
'''
234+
expected = {
235+
'reporters': [{
236+
'firstName': 'ABA',
237+
'lastName': 'X',
238+
'email': None
239+
},
240+
{
241+
'firstName': 'ABO',
242+
'lastName': 'Y',
243+
'email': None
244+
}]
245+
}
246+
schema = graphene.Schema(query=Query)
247+
result = schema.execute(query, context_value={'session': session})
248+
assert not result.errors
249+
assert result.data == expected
250+
251+
252+
def test_should_order_by_asc(session):
253+
setup_fixtures(session)
254+
255+
class ReporterType(SQLAlchemyObjectType):
256+
class Meta:
257+
model = Reporter
258+
259+
class Query(graphene.ObjectType):
260+
reporters = SQLAlchemyList(ReporterType, order_by='first_name ASC')
261+
262+
query = '''
263+
query ReporterQuery {
264+
reporters {
265+
firstName,
266+
lastName,
267+
email
268+
}
269+
}
270+
'''
271+
expected = {
272+
'reporters': [
273+
{
274+
'firstName': 'ABA',
275+
'lastName': 'X',
276+
'email': None
277+
},
278+
{
279+
'firstName': 'ABO',
280+
'lastName': 'Y',
281+
'email': None
282+
}
283+
]
284+
}
285+
schema = graphene.Schema(query=Query)
286+
result = schema.execute(query, context_value={'session': session})
287+
assert not result.errors
288+
assert result.data == expected
289+
290+
291+
def test_should_order_by_desc(session):
292+
setup_fixtures(session)
293+
294+
class ReporterType(SQLAlchemyObjectType):
295+
class Meta:
296+
model = Reporter
297+
298+
class Query(graphene.ObjectType):
299+
reporters = SQLAlchemyList(ReporterType, order_by='firstName desc')
300+
301+
query = '''
302+
query ReporterQuery {
303+
reporters {
304+
firstName,
305+
lastName,
306+
email
307+
}
308+
}
309+
'''
310+
expected = {
311+
'reporters': [
312+
{
313+
'firstName': 'ABO',
314+
'lastName': 'Y',
315+
'email': None
316+
},
317+
{
318+
'firstName': 'ABA',
319+
'lastName': 'X',
320+
'email': None
321+
}
322+
]
323+
}
324+
schema = graphene.Schema(query=Query)
325+
result = schema.execute(query, context_value={'session': session})
326+
assert not result.errors
327+
assert result.data == expected
328+
329+
96330
def test_should_node(session):
97331
setup_fixtures(session)
98332

99333
class ReporterNode(SQLAlchemyObjectType):
100-
101334
class Meta:
102335
model = Reporter
103-
interfaces = (Node, )
336+
interfaces = (Node,)
104337

105338
@classmethod
106339
def get_node(cls, id, info):
107340
return Reporter(id=2, first_name='Cookie Monster')
108341

109342
class ArticleNode(SQLAlchemyObjectType):
110-
111343
class Meta:
112344
model = Article
113-
interfaces = (Node, )
345+
interfaces = (Node,)
114346

115347
# @classmethod
116348
# def get_node(cls, id, info):
@@ -169,9 +401,9 @@ def resolve_article(self, *args, **kwargs):
169401
'email': None,
170402
'articles': {
171403
'edges': [{
172-
'node': {
173-
'headline': 'Hi!'
174-
}
404+
'node': {
405+
'headline': 'Hi!'
406+
}
175407
}]
176408
},
177409
},
@@ -197,10 +429,9 @@ def test_should_custom_identifier(session):
197429
setup_fixtures(session)
198430

199431
class EditorNode(SQLAlchemyObjectType):
200-
201432
class Meta:
202433
model = Editor
203-
interfaces = (Node, )
434+
interfaces = (Node,)
204435

205436
class Query(graphene.ObjectType):
206437
node = Node.Field()
@@ -247,29 +478,25 @@ def test_should_mutate_well(session):
247478
setup_fixtures(session)
248479

249480
class EditorNode(SQLAlchemyObjectType):
250-
251481
class Meta:
252482
model = Editor
253-
interfaces = (Node, )
483+
interfaces = (Node,)
254484

255485
class ReporterNode(SQLAlchemyObjectType):
256-
257486
class Meta:
258487
model = Reporter
259-
interfaces = (Node, )
488+
interfaces = (Node,)
260489

261490
@classmethod
262491
def get_node(cls, id, info):
263492
return Reporter(id=2, first_name='Cookie Monster')
264493

265494
class ArticleNode(SQLAlchemyObjectType):
266-
267495
class Meta:
268496
model = Article
269-
interfaces = (Node, )
497+
interfaces = (Node,)
270498

271499
class CreateArticle(graphene.Mutation):
272-
273500
class Arguments:
274501
headline = graphene.String()
275502
reporter_id = graphene.ID()

0 commit comments

Comments
 (0)