我想这样做:
def need_session(func):
@wraps(func)
def wrapper(*args, **kwargs):
session = SessionLocal()
try:
func(session, *args, **kwargs)
finally:
session.close()
我使用的是wraps
函数,因为我使用的是Strawberry,它取决于参数类型。
如您所见,func
有一个额外的session
参数。
我怎样才能使它工作?
如果我尝试使用Strawberry运行GraphQL服务器,其中的函数使用上面的装饰器进行装饰,它会给我这个错误:
TypeError: Mutation fields cannot resolved。异常类型'
'
如果我把装饰符改成这样:
def need_session(func):
@wraps(func)
def wrapper(*args, **kwargs):
session = SessionLocal()
kwargs['session'] = session
try:
func(*args, **kwargs)
finally:
session.close()
并将修饰函数的参数列表更改为:
def some_func(some_arg: SomeClass, **kwargs):
...
我仍然得到这个错误:
strawberry.exceptions。MissingArgumentsAnnotationsError:缺少参数的注释在"login_user"字段中,您是否忘记添加它?
为什么出现错误?
你得到这个异常,因为草莓不支持**kwargs
和每个strawberry.field
必须有注解的所有参数。它们是由strawberry.type
修饰器处理的,所以你不能修改函数签名。
可能解决方案1:
您可以通过编写模式扩展在StrawberryInfo
中提供会话。
的例子:
from strawberry.extensions import Extension
from mydb import get_db_session
class DbSessionMiddleWare(Extension):
def on_request_start(self):
self.execution_context.context["db"] = get_db_session()
def on_request_end(self):
self.execution_context.context["db"].close()
schema = strawberry.Schema(
query=Queries,
mutation=Mutations,
extensions=[
DbSessionMiddleWare,
],
)
一些解析器:
from strawberry.types import Info
def resolve_name(info: Info):
name = info.context['db'].execute("SELECT ...")
可能解决方案2:
你可以用你自己的装饰器包装Strawberry装饰器,并按你的意愿注入一些注释。
请记住,您应该从函数签名中清除任何*args
或**kwargs
,否则strawberry会抱怨这一点。
的例子:
from strawberry.arguments import StrawberryArgument, StrawberryAnnotation, UNSET
import inspect
def create_strawberry_argument(
python_name: str, graphql_name: str, type_, default=None
):
return StrawberryArgument(
python_name=python_name,
graphql_name=graphql_name,
type_annotation=StrawberryAnnotation(type_),
default=default or UNSET,
)
def hide_args_kwargs(field):
sig = inspect.signature(field)
cleared = tuple(
p for p in sig.parameters.values() if p.name not in ("kwargs", "args")
)
field.__signature__ = inspect.signature(field).replace(parameters=(cleared))
return field
def inject_mutation(field, arguments: tuple[str, type]):
field = hide_args_kwargs(field)
field = strawberry.mutation(field, description=field.__doc__)
for arg_tuple in arguments:
arg = create_strawberry_argument(arg_tuple[0], arg_tuple[0], arg_tuple[1])
field.arguments.append(arg)
return field
@inject_mutation(('arg2', int))
def some_resolver(info, arg1, **kwargs) -> SomeOutputType:
f = kwargs.get('arg2', None)