Skip to content

Commit f150f38

Browse files
committed
commit patch from PR#87 of original repository: graphql-python#87
1 parent fe4b493 commit f150f38

File tree

7 files changed

+1004
-36
lines changed

7 files changed

+1004
-36
lines changed

graphene_sqlalchemy/mutations.py

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
from graphene import Argument, Field, List, Mutation
2+
from graphene.types.objecttype import ObjectTypeOptions
3+
from graphene.types.utils import yank_fields_from_attrs
4+
from sqlalchemy.inspection import inspect as sqlalchemyinspect
5+
6+
from graphene_sqlalchemy.types import construct_fields
7+
from .registry import get_global_registry
8+
from .utils import get_session, get_snake_or_camel_attr
9+
10+
11+
class SQLAlchemyMutationOptions(ObjectTypeOptions):
12+
model = None # type: Model
13+
14+
15+
class SQLAlchemyCreate(Mutation):
16+
@classmethod
17+
def __init_subclass_with_meta__(cls, model=None, registry=None, only_fields=(), exclude_fields=None, **options):
18+
meta = SQLAlchemyMutationOptions(cls)
19+
meta.model = model
20+
21+
model_inspect = sqlalchemyinspect(model)
22+
cls._model_inspect = model_inspect
23+
24+
if not isinstance(exclude_fields, list):
25+
if exclude_fields:
26+
exclude_fields = list(exclude_fields)
27+
else:
28+
exclude_fields = []
29+
30+
for primary_key_column in model_inspect.primary_key:
31+
if primary_key_column.autoincrement:
32+
exclude_fields.append(primary_key_column.name)
33+
34+
for relationship in model_inspect.relationships:
35+
exclude_fields.append(relationship.key)
36+
37+
if not registry:
38+
registry = get_global_registry()
39+
40+
arguments = yank_fields_from_attrs(
41+
construct_fields(model, registry, only_fields, exclude_fields),
42+
_as=Argument,
43+
)
44+
45+
super(SQLAlchemyCreate, cls).__init_subclass_with_meta__(_meta=meta, arguments=arguments, **options)
46+
47+
@classmethod
48+
def mutate(cls, self, info, **kwargs):
49+
session = get_session(info.context)
50+
51+
meta = cls._meta
52+
53+
model = meta.model()
54+
session.add(model)
55+
56+
for key, value in kwargs.items():
57+
setattr(model, key, value)
58+
59+
session.commit()
60+
61+
return model
62+
63+
@classmethod
64+
def Field(cls, *args, **kwargs):
65+
return Field(
66+
cls._meta.output, args=cls._meta.arguments, resolver=cls._meta.resolver
67+
)
68+
69+
70+
class SQLAlchemyUpdate(Mutation):
71+
@classmethod
72+
def __init_subclass_with_meta__(cls, model=None, registry=None, only_fields=(), exclude_fields=None, **options):
73+
meta = SQLAlchemyMutationOptions(cls)
74+
meta.model = model
75+
76+
model_inspect = sqlalchemyinspect(model)
77+
cls._model_inspect = model_inspect
78+
79+
if not isinstance(exclude_fields, list):
80+
if exclude_fields:
81+
exclude_fields = list(exclude_fields)
82+
else:
83+
exclude_fields = []
84+
85+
for relationship in model_inspect.relationships:
86+
exclude_fields.append(relationship.key)
87+
88+
if not registry:
89+
registry = get_global_registry()
90+
91+
arguments = yank_fields_from_attrs(
92+
construct_fields(model, registry, only_fields, exclude_fields),
93+
_as=Argument
94+
)
95+
96+
super(SQLAlchemyUpdate, cls).__init_subclass_with_meta__(_meta=meta, arguments=arguments, **options)
97+
98+
@classmethod
99+
def mutate(cls, self, info, **kwargs):
100+
session = get_session(info.context)
101+
102+
meta = cls._meta
103+
104+
query = session.query(meta.model)
105+
for primary_key_column in cls._model_inspect.primary_key:
106+
query = query.filter(getattr(meta.model, primary_key_column.key) == kwargs[primary_key_column.name])
107+
model = query.one()
108+
109+
for key, value in kwargs.items():
110+
setattr(model, key, value)
111+
112+
session.commit()
113+
114+
return model
115+
116+
@classmethod
117+
def Field(cls, *args, **kwargs):
118+
return Field(
119+
cls._meta.output, args=cls._meta.arguments, resolver=cls._meta.resolver
120+
)
121+
122+
123+
class SQLAlchemyDelete(Mutation):
124+
@classmethod
125+
def __init_subclass_with_meta__(cls, model=None, registry=None, only_fields=(),
126+
exclude_fields=None, **options):
127+
meta = SQLAlchemyMutationOptions(cls)
128+
meta.model = model
129+
130+
model_inspect = sqlalchemyinspect(model)
131+
cls._model_inspect = model_inspect
132+
133+
only_fields = []
134+
exclude_fields = ()
135+
for primary_key_column in model_inspect.primary_key:
136+
only_fields.append(primary_key_column.name)
137+
138+
if not registry:
139+
registry = get_global_registry()
140+
141+
arguments = yank_fields_from_attrs(
142+
construct_fields(model, registry, only_fields, exclude_fields),
143+
_as=Argument
144+
)
145+
146+
super(SQLAlchemyDelete, cls).__init_subclass_with_meta__(_meta=meta, arguments=arguments, **options)
147+
148+
@classmethod
149+
def mutate(cls, self, info, **kwargs):
150+
session = get_session(info.context)
151+
152+
meta = cls._meta
153+
154+
query = session.query(meta.model)
155+
156+
for primary_key_column in cls._model_inspect.primary_key:
157+
query = query.filter(getattr(meta.model, primary_key_column.key) == kwargs[primary_key_column.name])
158+
model = query.one()
159+
session.delete(model)
160+
161+
session.commit()
162+
163+
return model
164+
165+
@classmethod
166+
def Field(cls, *args, **kwargs):
167+
return Field(
168+
cls._meta.output, args=cls._meta.arguments, resolver=cls._meta.resolver
169+
)
170+
171+
172+
class SQLAlchemyListDelete(Mutation):
173+
@classmethod
174+
def __init_subclass_with_meta__(cls, model=None, registry=None, only_fields=(),
175+
exclude_fields=None, **options):
176+
meta = SQLAlchemyMutationOptions(cls)
177+
meta.model = model
178+
179+
model_inspect = sqlalchemyinspect(model)
180+
for column in model_inspect.columns:
181+
column.nullable = True
182+
183+
cls._model_inspect = model_inspect
184+
185+
if not isinstance(exclude_fields, list):
186+
if exclude_fields:
187+
exclude_fields = list(exclude_fields)
188+
else:
189+
exclude_fields = []
190+
191+
for relationship in model_inspect.relationships:
192+
exclude_fields.append(relationship.key)
193+
194+
if not registry:
195+
registry = get_global_registry()
196+
197+
arguments = yank_fields_from_attrs(
198+
construct_fields(model, registry, only_fields, exclude_fields),
199+
_as=Argument
200+
)
201+
202+
super(SQLAlchemyListDelete, cls).__init_subclass_with_meta__(_meta=meta, arguments=arguments, **options)
203+
204+
@classmethod
205+
def mutate(cls, self, info, **kwargs):
206+
session = get_session(info.context)
207+
208+
meta = cls._meta
209+
210+
query = session.query(meta.model)
211+
for key, value in kwargs.items():
212+
query = query.filter(get_snake_or_camel_attr(meta.model, key) == value)
213+
214+
models = query.all()
215+
for model in models:
216+
session.delete(model)
217+
218+
session.commit()
219+
220+
return models
221+
222+
@classmethod
223+
def Field(cls, *args, **kwargs):
224+
return Field(
225+
cls._meta.output, args=cls._meta.arguments, resolver=cls._meta.resolver
226+
)
227+
228+
229+
def create(of_type):
230+
class CreateModel(SQLAlchemyCreate):
231+
class Meta:
232+
model = of_type._meta.model
233+
234+
Output = of_type
235+
236+
return CreateModel.Field()
237+
238+
239+
def update(of_type):
240+
class UpdateModel(SQLAlchemyUpdate):
241+
class Meta:
242+
model = of_type._meta.model
243+
244+
Output = of_type
245+
246+
return UpdateModel.Field()
247+
248+
249+
def delete(of_type):
250+
class DeleteModel(SQLAlchemyDelete):
251+
class Meta:
252+
model = of_type._meta.model
253+
254+
Output = of_type
255+
256+
return DeleteModel.Field()
257+
258+
259+
def delete_all(of_type):
260+
class DeleteListModel(SQLAlchemyListDelete):
261+
class Meta:
262+
model = of_type._meta.model
263+
264+
Output = List(of_type)
265+
266+
return DeleteListModel.Field()

graphene_sqlalchemy/tests/conftest.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import pytest
2+
from sqlalchemy import create_engine
3+
4+
5+
@pytest.fixture(scope='session')
6+
def db():
7+
return create_engine('sqlite:///test_sqlalchemy.sqlite3')

0 commit comments

Comments
 (0)