Saleor调用schema.execute执行GraphQL报'NoneType'无app属性错误
问题产生原因
- Saleor 原生 GraphQL Resolver 对上下文的读取逻辑是属性访问模式,也就是统一通过
info.context.xxx的方式取值,不支持普通字典的键值对访问。你传入字典作为context_value时,resolver执行context.app的取值操作,自然会抛出'dict' object has no attribute 'app'的错误。 - 第一次报错
'NoneType' object has no attribute 'app',是因为你手动初始化Schema的方式错误:仅传入ProductQueries构造的graphene.Schema缺失了Saleor原生查询依赖的中间件、关联类型、上下文注入逻辑,执行链路中context没有被正确传递,拿到的是None值,点取app属性就会触发空对象错误。 - 自定义查询/变更能正常运行,是因为你自己写的resolver用了字典键读取的逻辑(比如
info.context["app"]),和你传的字典上下文匹配,和Saleor原生resolver的逻辑不兼容。
修复方案
按照以下步骤调整即可:
- 不要手动拼接初始化Schema,直接导入Saleor项目预构建好的完整Schema实例,避免缺失内置依赖:
# 导入Saleor自带的完整schema from saleor.graphql.api import schema - 构造支持属性访问的上下文对象,不要直接传普通字典。可以用Python标准库的
SimpleNamespace快速构造,同时补全Saleor原生resolver依赖的基础字段:from types import SimpleNamespace # 按需配置上下文字段,涉及权限操作时传入有权限的User/App实例即可 context = SimpleNamespace( app=None, user=None, channel="default-channel", dataloaders={}, # 初始化空dataloader字典,避免批量查询逻辑报错 plugins=None, ) - 执行查询时传入构造好的上下文对象即可,修正后的完整测试代码:
from saleor.graphql.api import schema from types import SimpleNamespace query = """ { products(first: 2, channel: "default-channel") { edges { node { id name defaultVariant{ id } } } } } """ context = SimpleNamespace( app=None, user=None, channel="default-channel", dataloaders={} ) result = schema.execute(query, context_value=context) # 优先打印错误排查问题,无错误后再取返回数据 if result.errors: print(result.errors) print(result.data)
补充说明:如果是在Web请求生命周期外(比如定时任务、内部运维脚本)调用,需要提前初始化好Django运行环境,确保数据库连接、配置加载正常;涉及权限校验的查询/变更,需要给context中的
user或app字段传入对应权限的实例,否则会触发权限拒绝错误。
内容的提问来源于stack exchange,提问作者Shivam Maithil
相关产品推荐
相关产品推荐

