大朗喝药啦 發表於 2019-10-16 12:14:00

详解Python Graphql

<h1>前言</h1>
<p>很高兴现在接手的项目让我接触到了Python Graphql,百度上对其介绍相对较少也不够全面,几乎没有完整的中文文档,所以这边也借此机会学习一下Graphql。</p>
<p><strong>什么是Graphql呢</strong>?</p>
<p>Graphql是一个API查询语言,其数据由服务器上的一个Scheme提供,其查询返回的数据依赖请求的时候用户需要的精确数据。列如用户只需要一个name字段,服务器也只返回name的值。</p>
<p><strong>参考</strong></p>
<p>英文学习文档:https://graphene-python.org/</p>
<p>更多example关注:https://github.com/graphql-python/graphene/tree/master/examples</p>
<h1>Hello Word 入门</h1>
<p>先看下面一个例子,查询语句为{ hello(name:"gaojiayi") } 定义了要查询的入口,以及传入的参数。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> graphene <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ObjectType, String, Schema

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">定义一个字符串属性域hello 且有一个字符串参数为name,设置name的默认</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
    hello </span>= String(name = String(default_value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gaojy</span><span style="color: rgba(128, 0, 0, 1)">"</span>,required=<span style="color: rgba(0, 0, 0, 1)">True))

    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> resolve_hello定义了上面hello的实现,并返回查询结果</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 一般resolve需要加上固定前缀resolve_</span>
<span style="color: rgba(0, 0, 0, 1)">    @staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_hello(root,info,name):
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello word -- {name}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">

schema </span>= Schema(query=<span style="color: rgba(0, 0, 0, 1)">Query)

</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    query_string </span>= <span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">{ hello(name:"gaojiayi") }</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)">
    result </span>=<span style="color: rgba(0, 0, 0, 1)"> schema.execute(query_string)
    </span><span style="color: rgba(0, 0, 255, 1)">print</span>(result.data[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">'</span>])</pre>
</div>
<h1>&nbsp;Graphql中的Types</h1>
<h2>Scheme</h2>
<p>下面定义了一个Scheme,其中MyRootQuery,MyRootMutation,MyRootSubscription都是继承了graphene&nbsp;.objectType,但是不同之处在于query定义了查询数据的入口,而mutation用来数据改变或者数据恢复,而subscription是用来实时呈现数据的变化给client。type是用来指定返回数据的精确类型,列如返回的数据是一个interface,但是有多个类型继承了该interface,这时候需要指定一个具体的实现来返回给client。</p>
<div class="cnblogs_code">
<pre>my_schema =<span style="color: rgba(0, 0, 0, 1)"> Schema(
    query</span>=<span style="color: rgba(0, 0, 0, 1)">MyRootQuery,
    mutation</span>=<span style="color: rgba(0, 0, 0, 1)">MyRootMutation,
    subscription</span>=<span style="color: rgba(0, 0, 0, 1)">MyRootSubscription,<br>   type=[</span><span class="n">SomeExtraObjectType,</span><span>]<br> )</span></pre>
</div>
<p>另外查询字符串默认为驼峰命名,列如</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> graphene <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ObjectType, String, Schema

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    other_name </span>= String(name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">_other_Name</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    @staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_other_name(root, info):
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">test CamelCase</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">


schema </span>= Schema(query=<span style="color: rgba(0, 0, 0, 1)">Query)

</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 查询数默认使用otherName,此处用了别名。</span>
    result = schema.execute(<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">{_other_Name}</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)">)
    </span><span style="color: rgba(0, 0, 255, 1)">print</span>(result.data[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">_other_Name</span><span style="color: rgba(128, 0, 0, 1)">'</span>])</pre>
</div>
<p>如果关闭默认驼峰命名方式,则可以在定义scheme的时候加上<span class="n"><span class="o"><span class="n"><span class="p"><span class="n"><span class="o"><span class="n"><span class="p"><span class="n">auto_camelcase<span class="o">=<span class="kc">False</span></span></span></span></span></span></span></span></span></span></span></p>
<pre><span class="n">my_schema <span class="o">= <span class="n">Schema<span class="p">(
<span class="n"><span class="o"><span class="n"><span class="p">    <span class="n">auto_camelcase<span class="o">=<span class="kc">False<span class="p">
<span class="p">)<br></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<h2>scalars</h2>
<p>scalars type可以理解为用来定义Field,它可以传入以下几种可选参数,例如</p>
<p><em>other_name = String(name='_other_Name',required=True,description="",deprecation_reason="",defalut_value=Any)</em></p>
<p>&nbsp;</p>
<p>常见的基本saclars type有如下几个:</p>
<div class="cnblogs_code"><img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_3686ec43-9740-4fc5-ba13-2b0cf17dbb20" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_3686ec43-9740-4fc5-ba13-2b0cf17dbb20" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">graphene.String
graphene.Int
graphene.Float
graphene.Boolean
graphene.ID
graphene.types.datetime.Date
graphene.types.datetime.DateTime
graphene.types.datetime.Time
graphene.types.json.JSONString</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<p>saclars type的挂载在objectType,interface,Mutation中的field域中。</p>
<div class="cnblogs_code"><img id="code_img_closed_b6aa42af-2bdf-4539-94b0-6c532301ab27" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_b6aa42af-2bdf-4539-94b0-6c532301ab27" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_b6aa42af-2bdf-4539-94b0-6c532301ab27" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> Is equivalent to:</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(graphene.ObjectType):
    name </span>= graphene.Field(graphene.String)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<h2>Lists and Non-Null</h2>
<p>Non-Null</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> graphene

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Character(graphene.ObjectType):
    name </span>= graphene.String(required=<span style="color: rgba(0, 0, 0, 1)">True)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">等价于 即返回的数据如果name=null,则会报错</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Character(graphene.ObjectType):
    name </span>= graphene.String(required=True)</pre>
</div>
<p>Lists</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> graphene

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Character(graphene.ObjectType):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> appears_in表示为一个非null元素的列表</span>
    appears_in = graphene.List(graphene.NonNull(graphene.String))</pre>
</div>
<h2>&nbsp;</h2>
<h2>ObjectType</h2>
<p>objectType是在scheme中用来定义Fields之间联系以及数据流转的python类,每一个obejctType属性表示一个Field,每个Field定义一个resolve方法用来获取数据,如果没有定义,则使用一个默认的resolver。</p>
<p>&nbsp;接下来看一个例子。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> graphene <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ObjectType, String, Schema

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    @staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_hello(parent,info,name):
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello word -- {name}</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
<p>上面的resolve_hello有三个参数,分别是parent,info,name</p>
<p>1 parent通常用来获取objectType内的其他field的值,而在根query中默认为None,看下面的事例,当OjectType的Field为saclar type,则parent不会再向下传递。</p>
<div class="cnblogs_code"><img id="code_img_closed_834df17a-bd82-4e6d-b999-6785e7060f70" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_834df17a-bd82-4e6d-b999-6785e7060f70" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_834df17a-bd82-4e6d-b999-6785e7060f70" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(ObjectType):
    full_name </span>=<span style="color: rgba(0, 0, 0, 1)"> String()

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_full_name(parent, info):
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{parent.first_name} {parent.last_name}</span><span style="color: rgba(128, 0, 0, 1)">"</span>

<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    me </span>=<span style="color: rgba(0, 0, 0, 1)"> Field(Person)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_me(parent, info):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> returns an object that represents a Person</span>
      <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 这里的parent为None</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> get_human(name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Luke Skywalker</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>当然,根查询的parent也可以初始化值,就是在execute的时候添加root变量</p>
<div class="cnblogs_code"><img id="code_img_closed_8e285880-13ae-44a4-a81a-4a62b3f96c01" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_8e285880-13ae-44a4-a81a-4a62b3f96c01" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_8e285880-13ae-44a4-a81a-4a62b3f96c01" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">    @staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_hello(parent, info, name):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印结果 man ,parent默认为root的值</span>
      <span style="color: rgba(0, 0, 255, 1)">print</span>(parent[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">sex</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">])
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello word -- {name}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">


schema </span>= Schema(query=Query, mutation=<span style="color: rgba(0, 0, 0, 1)">MyMutations)

</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    query_string </span>= <span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">{ hello(name:"gaojiayi") }</span><span style="color: rgba(128, 0, 0, 1)">'''</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 指定root的值</span>
    result = schema.execute(query_string, root={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">sex</span><span style="color: rgba(128, 0, 0, 1)">'</span>: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">man</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
    </span><span style="color: rgba(0, 0, 255, 1)">print</span>(result.data[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">'</span>])</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>当查询语句存在多个的时候,可指定执行那一条语句</p>
<div class="cnblogs_code"><img id="code_img_closed_32716bb5-ad29-46af-8cdd-f8db896ab0e1" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_32716bb5-ad29-46af-8cdd-f8db896ab0e1" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_32716bb5-ad29-46af-8cdd-f8db896ab0e1" class="cnblogs_code_hide">
<pre>schema =<span style="color: rgba(0, 0, 0, 1)"> Schema(Query)
query_string </span>= <span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
    query getUserWithFirstName {
      user {
            id
            firstName
            lastName
      }
    }
    query getUserWithFullName {
      user {
            id
            fullName
      }
    }
</span><span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(0, 0, 0, 1)">
result </span>=<span style="color: rgba(0, 0, 0, 1)"> schema.execute(
    query_string,
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 指定执行第二条语句</span>
    operation_name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">getUserWithFullName</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
)</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>2 info表示请求的上下文,可以在查询语中添加context,列如</p>
<div class="cnblogs_code"><img id="code_img_closed_c81ddd40-5c04-499f-8b2a-e0edaa3207bc" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_c81ddd40-5c04-499f-8b2a-e0edaa3207bc" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_c81ddd40-5c04-499f-8b2a-e0edaa3207bc" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
   hello </span>= String(name=String(default_value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gaojy</span><span style="color: rgba(128, 0, 0, 1)">"</span>, required=<span style="color: rgba(0, 0, 0, 1)">True))
   @staticmethod
   </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_hello(root, info, name):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 通过info可获取上下文内容</span>
      <span style="color: rgba(0, 0, 255, 1)">print</span>(info.context.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">company</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello word -- {name}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">


schema </span>= Schema(query=Query, mutation=<span style="color: rgba(0, 0, 0, 1)">MyMutations)

</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
    query_string </span>= <span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">{ hello(name:"gaojiayi") }</span><span style="color: rgba(128, 0, 0, 1)">'''</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1 execute中添加context</span>
    result = schema.execute(query_string, context={<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">company</span><span style="color: rgba(128, 0, 0, 1)">'</span>: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">baidu</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
    </span><span style="color: rgba(0, 0, 255, 1)">print</span>(result.data[<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">'</span>])</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>3 name表示请求时带的参数,可以参考hello word事例,如有多个参数可形参**kwargs</p>
<div class="cnblogs_code"><img id="code_img_closed_e08ae7ea-778e-4afb-a15d-edbaae634434" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_e08ae7ea-778e-4afb-a15d-edbaae634434" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_e08ae7ea-778e-4afb-a15d-edbaae634434" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> graphene <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ObjectType, String

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    hello </span>= String(required=True, name=<span style="color: rgba(0, 0, 0, 1)">String())

    </span><span style="color: rgba(0, 0, 255, 1)">def</span> resolve_hello(parent, info, **<span style="color: rgba(0, 0, 0, 1)">kwargs):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> name 为None 则name = World</span>
      name = kwargs.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">World</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Hello, {name}!</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>4 默认resolver:列如一个objectType的field都没有指定队友的resolve,那么对象默认会序列化一个字典。</p>
<div class="cnblogs_code"><img id="code_img_closed_6d1e7906-d2c5-4afe-83e6-b04ddec309e2" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_6d1e7906-d2c5-4afe-83e6-b04ddec309e2" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_6d1e7906-d2c5-4afe-83e6-b04ddec309e2" class="cnblogs_code_hide">
<pre>PersonValueObject = namedtuple(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Person</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">first_name</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">last_name</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(ObjectType):
    first_name </span>=<span style="color: rgba(0, 0, 0, 1)"> String()
    last_name </span>=<span style="color: rgba(0, 0, 0, 1)"> String()

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
    me </span>=<span style="color: rgba(0, 0, 0, 1)"> Field(Person)
    my_best_friend </span>=<span style="color: rgba(0, 0, 0, 1)"> Field(Person)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_me(parent, info):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> always pass an object for `me` field</span>
      <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> {"firstName": "Luke", "lastName": "Skywalker"}</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> PersonValueObject(first_name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Luke</span><span style="color: rgba(128, 0, 0, 1)">'</span>, last_name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Skywalker</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;5 meta 类:用于objectType的配置</p>
<h2>Enum</h2>
<div class="cnblogs_code"><img id="code_img_closed_a528945f-7258-442d-bed1-5f1054adaba2" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_a528945f-7258-442d-bed1-5f1054adaba2" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_a528945f-7258-442d-bed1-5f1054adaba2" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Episode(graphene.Enum):
    NEWHOPE </span>= 4<span style="color: rgba(0, 0, 0, 1)">
    EMPIRE </span>= 5<span style="color: rgba(0, 0, 0, 1)">
    JEDI </span>= 6<span style="color: rgba(0, 0, 0, 1)">

    @property
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> description(self):
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> self ==<span style="color: rgba(0, 0, 0, 1)"> Episode.NEWHOPE:
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">New Hope Episode</span><span style="color: rgba(128, 0, 0, 1)">'</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Other episode</span><span style="color: rgba(128, 0, 0, 1)">'</span>

<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(ObjectType):
         desc1 </span>=<span style="color: rgba(0, 0, 0, 1)"> String(
      v</span>=Argument(Episode, default_value=<span style="color: rgba(0, 0, 0, 1)">Episode.NEWHOPE.value),
      description</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">default value in schema is `4`, which is not valid. Also, awkward to write.</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

@staticmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_desc1(parent, info,v):
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> f<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">argument: {v!r}</span><span style="color: rgba(128, 0, 0, 1)">'</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 使用下面的方式可以将python类型的enum转化成saclars类型</span>
<span style="color: rgba(0, 0, 0, 1)">graphene.Enum.from_enum(
    AlreadyExistingPyEnum,
    description</span>=<span style="color: rgba(0, 0, 255, 1)">lambda</span> v: <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">foo</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">if</span> v == AlreadyExistingPyEnum.Foo <span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">bar</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<h2>Interfaces</h2>
<p>顾名思义,接口,其他的obectType可以继承接口,示例如下</p>
<div class="cnblogs_code"><img id="code_img_closed_838a258d-9d1d-477a-991f-5574a3f2e8fd" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_838a258d-9d1d-477a-991f-5574a3f2e8fd" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_838a258d-9d1d-477a-991f-5574a3f2e8fd" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> graphene

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Character(graphene.Interface):
    id </span>= graphene.ID(required=<span style="color: rgba(0, 0, 0, 1)">True)
    name </span>= graphene.String(required=<span style="color: rgba(0, 0, 0, 1)">True)
    friends </span>= graphene.List(<span style="color: rgba(0, 0, 255, 1)">lambda</span><span style="color: rgba(0, 0, 0, 1)">: Character)

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">继承Character</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Human(graphene.ObjectType):
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Meta:
      interfaces </span>=<span style="color: rgba(0, 0, 0, 1)"> (Character, )

    starships </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.List(Starship)
    home_planet </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">继承Character</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Droid(graphene.ObjectType):
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Meta:
      interfaces </span>=<span style="color: rgba(0, 0, 0, 1)"> (Character, )

    primary_function </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Query(graphene.ObjectType):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回的类型是Character</span>
    hero =<span style="color: rgba(0, 0, 0, 1)"> graphene.Field(
      Character,
      required</span>=<span style="color: rgba(0, 0, 0, 1)">True,
      episode</span>=graphene.Int(required=<span style="color: rgba(0, 0, 0, 1)">True)
    )

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_hero(root, info, episode):
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> Luke is the hero of Episode V</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> episode == 5<span style="color: rgba(0, 0, 0, 1)">:
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> get_human(name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Luke Skywalker</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> get_droid(name=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">R2-D2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">对于返回数据具体类型,可以在type属性中列举</span>
schema = graphene.Schema(query=Query, types=)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>另外scheme中如果没有指定type,会报错</p>
<p><span class="s2">"Abstract type Character must resolve to an Object type at runtime for field Query.hero ..."</span></p>
<p><span class="s2">可以在interface中重写resolve_type方法</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Character(graphene.Interface):
    id </span>= graphene.ID(required=<span style="color: rgba(0, 0, 0, 1)">True)
    name </span>= graphene.String(required=<span style="color: rgba(0, 0, 0, 1)">True)
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回数据的时候,可以转换成具体的数据类型</span>
<span style="color: rgba(0, 0, 0, 1)">    @classmethod
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> resolve_type(cls, instance, info):
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> instance.type == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">DROID</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Droid
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> Human</pre>
</div>
<h2>Union</h2>
<p>该scalars type用来组合多个ObjectType,列如</p>
<div class="cnblogs_code"><img id="code_img_closed_7e70906f-e253-4fa0-bc03-c0cfc970f023" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_7e70906f-e253-4fa0-bc03-c0cfc970f023" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_7e70906f-e253-4fa0-bc03-c0cfc970f023" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> graphene

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Human(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()
    born_in </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Droid(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()
    primary_function </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Starship(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()
    length </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Int()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> SearchResult组合了Human Droid Starship所有的Fields</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SearchResult(graphene.Union):
    </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Meta:
      types </span>= (Human, Droid, Starship)</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<h2>Mutations</h2>
<p>如果说query是一个http get请求,那么Mutations可以看做是一个http post put请求。</p>
<p>def Mutate作为一个特殊的resover,当被调用的时候意在改变Mutation内的数据。</p>
<p>看下面一个操作示例</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">具体的操作类</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CreatePerson(graphene.Mutation):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 请求提交的参数,同样需要传递到mutate中</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Arguments:
      name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()

    ok </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Boolean()
    person </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Field(Person)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> mutate(root, info, name):
      person </span>= Person(name=<span style="color: rgba(0, 0, 0, 1)">name)
      ok </span>=<span style="color: rgba(0, 0, 0, 1)"> True
      </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">可执行具体的业务逻辑 包括写表 发消息等等</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span> CreatePerson(person=person, ok=<span style="color: rgba(0, 0, 0, 1)">ok)


</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> Mutation</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyMutations(graphene.ObjectType):
    create_person </span>=<span style="color: rgba(0, 0, 0, 1)"> CreatePerson.Field()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">指定mutationMyMutations</span>
schema = Schema(query=Query,mutation=MyMutations)</pre>
</div>
<p>执行结果如下:</p>
<p><img alt="" width="633" height="174" data-src="https://img2018.cnblogs.com/blog/1135670/201910/1135670-20191016120429772-494033859.png"></p>
<p>&nbsp;</p>
<p>Mutation下可申明InputFields 和InputObjectTypes类型的出入参,其中InputFields可以定义复合型入参,Output可指定复合型出参。</p>
<p>例1:InputFields&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DataInput(graphene.InputObjectType):
    user_name </span>=<span style="color: rgba(0, 0, 0, 1)"> String()
    basic_age </span>=<span style="color: rgba(0, 0, 0, 1)"> Int()

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()
    age </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Int()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 具体的操作类</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CreatePerson(graphene.Mutation):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 请求提交的参数,同样需要传递到mutate中</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Arguments:
      data </span>= DataInput(required=<span style="color: rgba(0, 0, 0, 1)">True)

    ok </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Boolean()
    person </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Field(Person)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> mutate(root, info, data):
      person </span>= Person(name=data.user_name, age=data.basic_age * 10<span style="color: rgba(0, 0, 0, 1)">)
      ok </span>=<span style="color: rgba(0, 0, 0, 1)"> True
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> CreatePerson(person=person, ok=ok)</pre>
</div>
<p>执行结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1135670/201910/1135670-20191016155500099-589337239.png"></p>
<p>&nbsp;</p>
<p>&nbsp;例2:InputObjectTypes</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DataInput(graphene.InputObjectType):
    user_name </span>=<span style="color: rgba(0, 0, 0, 1)"> String()
    basic_age </span>=<span style="color: rgba(0, 0, 0, 1)"> Int()


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Person(graphene.ObjectType):
    name </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.String()
    age </span>=<span style="color: rgba(0, 0, 0, 1)"> graphene.Int()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 具体的操作类</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CreatePerson(graphene.Mutation):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 请求提交的参数,同样需要传递到mutate中</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Arguments:
      data </span>= DataInput(required=<span style="color: rgba(0, 0, 0, 1)">True)
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定义一个Output 且指定class ,在mutate方法中返回实例</span>
    Output =<span style="color: rgba(0, 0, 0, 1)"> Person
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> mutate(root, info, data):
      person </span>= Person(name=data.user_name, age=data.basic_age * 10<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> person</pre>
</div>
<p>运行结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1135670/201910/1135670-20191016155842949-353858570.png"></p>
<h1>&nbsp;relay</h1>
<p>relay类似于react js中的redux,VUE中的vuex,可以缓存server端数据,加快查询并提供更新机制。example可参考前言中的example。</p>
<p>&nbsp;</p>
<h1>小结</h1>
<p>&nbsp; <strong>技术本身就是为业务服务,读者会问Graphql究竟可以使用在哪些业务场景呢?</strong></p>
<p>  官方有这么一句话ask exactly what you want.如果一个前端的接口只需要返回部分数据,而另一个前端接口也只需要返回部分数据,这两份数据有可能有交集,也可能没有。传统的做法可能需要开发两个接口或者一个接口内不断的if else来根据前端的具体场景去过滤某些数据。使用Graphql能够根据client指定需要哪些参数,后端scheme返回哪些参数,而后端只需要一个API可以查询到数据全集,Graphql可以自动完成数据解析,封装,过滤操作。</p>
<p>&nbsp;</p>
<pre></pre><br><br>
来源:https://www.cnblogs.com/gaojy/p/11678191.html
頁: [1]
查看完整版本: 详解Python Graphql