石墨烯 Django 和 react-router-relay

Posted

技术标签:

【中文标题】石墨烯 Django 和 react-router-relay【英文标题】:Graphene Django and react-router-relay 【发布时间】:2017-08-20 20:45:01 【问题描述】:

我在弄清楚 Graphene Django 应该如何与 react-router-relay 一起使用时遇到了很大的麻烦。假设我可以通过我的 Django 服务器上的 GraphiQL 控制台很好地使用以下 GraphQL 查询:

query 
  allThreads 
    edges 
      node 
        id
      
    
  

这大概是 Graphene 对常用的 viewer 包装器的替代品,因为 Relay 不支持根查询上的连接。所以我知道 allThreads 实际上是一个节点(类型为 ThreadNodeConnection),并且有一个可以查询的边连接。

问题是我不知道如何将它与 Relay 一起使用,特别是 react-router-relay。我有一个 React 视图,上面有这样的片段(在其他地方有一个子 Thread 组件):

fragments: 
      store: () => Relay.QL`
        fragment on Query 
          allThreads (first:300) 
            edges 
              node 
                // child's fragment included here
              
            ,
          
        
      `,
    ,

Webpack 会根据我的实时模式检查它并喜欢它。然后我在我的 index.js 中为路由器创建以下内容:

const ViewerQueries = 
  store: () => Relay.QL`query  allThreads(first:300) `
;

ReactDOM.render(
  <Router
    forceFetch
    environment=Relay.Store
    render=applyRouterMiddleware(useRelay)
    history=browserHistory
  >
    <Route path='/' component=ThreadList queries=ViewerQueries />
  </Router>
  , document.getElementById('container')
)

我已经有点不确定了,因为我认为我做错了 ViewerQueries,但很难知道,因为其他人都使用它来适应他们的 GraphQL 连接上的 viewer 包装器,但 Graphene 有一个不同的包装器每个连接,所以这可能只适用于我的单一路线,但现在没关系。 Webpack 再次喜欢它反对模式。但是当我加载页面时,我收到一个“错误请求”和以下错误:

"F1 片段不能作为类型的对象在这里传播 ThreadNodeConnection 永远不能是 Query 类型”

老实说,这就是我无法继续的地方,因为我显然不了解 Graphene Django 如何构建架构,或者应该如何编写 GraphQL 片段,或者应该如何编写 Route 查询.问题是我无法弄清楚这些事情中的哪一个是错误的,而且似乎没有任何资源围绕着使用这些特定技术组合的人们。

为了完整起见,我的 Graphene Django 架构设置是(略微简化):

项目/线程/schema.py:

class ThreadNode(DjangoObjectType):
    class Meta:
        model = Thread
        interfaces = (relay.Node, )

...

class Query(graphene.AbstractType):
    all_threads = DjangoFilterConnectionField(ThreadNode)
    thread = relay.Node.Field(ThreadNode, id=graphene.Int())

    def resolve_all_threads(self, args, context, info):
        return Thread.objects.select_related('author__profile').all()

    def resolve_thread(self, args, context, info):
        id = args.get('id')

        if id is not None:
            return Thread.objects.get(pk=id)

        return None

项目/schema.py:

class Query(project.threads.schema.Query, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

如果有人以前使用过这种特殊组合并有任何建议,那就太棒了。

【问题讨论】:

这与石墨烯无关。您要做的是使用连接字段作为根字段。这在 Relay 1 中不受支持,但应该在 Relay 2 中。完整的解释在这里:github.com/facebook/relay/issues/112 我认为这不是真的,我在问题中提到了这一点。石墨烯通过包装所有连接来绕过连接作为根的问题,因此连接成为一个节点,其上有可用的边连接。 我注意到“查询片段”这一行。您是否按照错误提示尝试了 ThreadNodeConnection 上的片段? 【参考方案1】:

我遇到了同样的问题,经过长时间的搜索,我终于找到了这个答案 https://github.com/facebook/relay/issues/1558#issuecomment-297010663

由于中继 1 不支持作为根查询的连接。您应该将查看器添加为节点接口来包装您的查询。 因此,在您的服务器主查询(project/schema.py)中,您应该添加以下代码:

class Query(project.threads.schema.Query, graphene.ObjectType):
   viewer = graphene.Field(lambda: Query)
   id = graphene.ID(required=True)

   def resolve_viewer(self, args, context, info):
    return info.parent_type

   def resolve_id(self, args, context, info):
      return 1

   class Meta:
      interfaces = (graphene.relay.Node,)

现在在你的 graphiql 中,你可以像这样格式化你的查询:

query 
  viewer
  allThreads(first:10) 
    edges 
      node 
        id
      
    
  


在客户端,您可以像这样创建容器:

export default Relay.createContainer(ThreadList, 
    fragments: 
        viewer: () => Relay.QL`
     fragment on Query 
          id
          allThreads(first:10)
            edges
              node
               id
               
            
          
      
    `,
    ,
);

希望对你有帮助

【讨论】:

以上是关于石墨烯 Django 和 react-router-relay的主要内容,如果未能解决你的问题,请参考以下文章

石墨烯 django 端点是不是同时需要 X-Csrftoken 和 CsrfCookie?

用石墨烯 django 数点赞

Django 模型对象和石墨烯 get_node

石墨烯 Django 和 react-router-relay

聚合石墨烯/django 查询中的字段

石墨烯 Django 获取物品