首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >用多层嵌套外键写入突变的Django Graphene

用多层嵌套外键写入突变的Django Graphene
EN

Stack Overflow用户
提问于 2020-10-18 21:47:29
回答 1查看 3.5K关注 0票数 3

如何编写嵌套外键的架构和查询?我检查了文档,没有找到如何做到这一点的例子。下面是我基于github和堆栈溢出回答的尝试,让我们说我有以下模型:

代码语言:javascript
运行
AI代码解释
复制
class Address(models.Model):
    name = models.CharField()

class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey('Address', on_delete=models.CASCADE, blank=False, null=False)

class Blog(models.Model):
    person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=False, null=False)
    text = models.TextField()

我试着编写了这样一个模式:

代码语言:javascript
运行
AI代码解释
复制
class AddressInput(graphene.InputObjectType):

    name = graphene.String(required=True)


class PersonInput(graphene.InputObjectType):

    name = graphene.String(required=True)
    address =graphene.Field(AddressInput)

class CreateNewBlog(graphene.Mutation):

    blog=graphene.Field(BlogType)

    class Arguments:
        address_data = AddressInput()
        person_data = PersonInput()
        text = graphene.String()

    @staticmethod
    def mutate(root, info, person_data=None, address_data=None, **input):

        address = Address.objects.create(name=address_data.name)
        person = Person.objects.create(address=address, name=person_data.name)
        blog = Blog.objects.create(person =person, text=input['text'])
        blog.save()

        return CreateNewBlog(blog=blog)

我用了这样的查询:

代码语言:javascript
运行
AI代码解释
复制
mutation {
        CreateNewBlog(person: { address: {name: "aaa"}, 
            name: "First Last" }, text: "hi hi") {
            Blog {
              person{
                name
                address{
                  name
                }
              },
              text
                
            }
        }
}

我收到了一条错误消息:

代码语言:javascript
运行
AI代码解释
复制
{
  "errors": [
    {
      "message": "'NoneType' object has no attribute 'name'",
      "locations": [
        {
          "line": 32,
          "column": 9
        }
      ],
      "path": [
        "CreateNewBlog"
      ]
    }
  ],
  "data": {
    "CreateNewBlog": null
  }
}

我认为问题在于我编写schema.py文件的方式。将InputFields嵌套到另一个InputField中不起作用的地方。还有其他方法来写一个突变吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-26 05:53:41

好吧这里有几件事。首先,您应该生成您的schema.graphql文件,因为这将显示Graphene构建的模式的实际最终形状,这将使您的调试变得更容易。或者,您可以使用GraphiQL测试查询,并让它的文档和自动完成为您完成繁重的工作。

但具体而言,你的石墨烯突变定义将产生一个突变,如下所示:

代码语言:javascript
运行
AI代码解释
复制
input AddressInput {
  name: String!
}

input PersonInput {
  name: String!
  address: AddressInput
}

type CreateNewBlogOutput {
  blog: Blog
}

type Mutation {
  CreateNewBlog(addressData: AddressInput, personData: PersonInput, text: String): CreateNewBlogOutput!
}

值得注意的是,在这里提供AddressInput有两种方法,一种是根方式,另一种是在PersonInput中。这可能不是你想要做的。其次,不需要任何根参数,这会导致错误消息非常无助,因为问题是您调用的是不正确的变异参数,但是查询验证器允许它通过,因为您的类型非常允许。

我相信,如果你像下面这样运行这种突变,它实际上会起作用:

代码语言:javascript
运行
AI代码解释
复制
mutation {
  CreateNewBlog(
    personData: {
      address: {
        name: "aaa"
      }, 
      name: "First Last"
    },
    text: "hi hi"
  ) {
    blog {
      person {
        name
        address {
          name
        }
      }
      text
    }
  }
}

我在这里只做了两个修改,person被更改为personData (为了与您的突变定义相匹配,Graphene会自动完成从蛇案例到骆驼案例的对话),以及在字段选择中将Blog更改为blog

但让我们再往前走一步,这是我如何制造突变的方法。

代码语言:javascript
运行
AI代码解释
复制
class AddressInput(graphene.InputObjectType):
    name = graphene.String(required=True)


class PersonInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    address = AddressInput(required=True)


class CreateNewBlogInput(graphene.InputObjectType):
    person = PersonInput(required=True)
    text = graphene.String(required=True)


class CreateNewBlogPayload(graphene.ObjectType):
    blog = graphene.Field(BlogType, required=True)


class CreateNewBlog(graphene.Mutation):
    class Arguments:
        input_data = CreateNewBlogInput(required=True, name="input")

    Output = CreateNewBlogPayload


    @staticmethod
    def mutate(root, info, input_data):
        address = Address.objects.create(name=input_data.person.address.name)
        person = Person.objects.create(address=address, name=input_data.person.name)
        blog = Blog.objects.create(person=person, text=input_data.text)
        blog.save()

        return CreateNewBlogPayload(blog=blog)

在构造Graphene的突变对象时,我还会将CreateNewBlog更改为createNewBlog,因为GraphQL惯例是使用较低的camel大小写进行突变。

然后你就会这样运行:

代码语言:javascript
运行
AI代码解释
复制
mutation {
  createNewBlog(
    input: {
      person: {
        address: {
          name: "aaa"
        }, 
        name: "First Last"
      }
      text: "hi hi"
    }
  ) {
    blog {
      person {
        name
        address {
          name
        }
      }
      text
    }
  }
}

为什么将整个输入封装在一个输入字段中?主要是因为它使得在使用变量时更容易在客户端调用变异,所以您可以只提供正确形状的单个输入arg,而不是多个。

代码语言:javascript
运行
AI代码解释
复制
// So instead of this
mutation OldCreateNewBlog($person: PersonInput, $text: String) {
  createNewBlog(
    personData: $person
    text: $text
  ) {
    blog {
      person {
        name
        address {
          name
        }
      }
      text
    }
  }
}

// You have this
mutation NewCreateNewBlog($input: CreateNewBlogInput!) {
  createNewBlog(
    input: $input
  ) {
    blog {
      person {
        name
        address {
          name
        }
      }
      text
    }
  }
}

后者使更改输入形状变得更容易,并且只需在客户端代码中的一个位置进行更改。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64421773

复制
相关文章
vim查找高亮关键字_emacs和vim
如果我们在在打开的文件中使用Vim搜索功能并开启搜索高亮显示后怎么取消当前高亮显示搜索关键字呢?
全栈程序员站长
2022/11/09
2.3K0
Tramp 使用指南
Tramp 是 Emacs 中用来编辑远端文件的模块,全称为『Transparent Remote (file) Access, Multiple Protocol』,类似于 VSCode 的 Remote Development,只不过比它年长 20 岁而已😄。这篇文章就来介绍下 tramp 的使用方式与注意事项。 使用方式 在使用 find-file 打开文件时,使用下面的语法,即可打开远端的文件: /method:user@host#port:path/to/file 比如, /ssh:vagrant
飞驰的西瓜
2022/07/26
9100
Tramp 使用指南
Emacs的Server Client模式
Emacs的server/client模式只需要加载一次配置文件,所以打开文件会快一些。
ExASIC
2022/03/29
9390
vim的编辑模式,命令模式以及vim的实践
vim编辑模式:               从一般模式进入编辑模式,只需按i、I、a、A、o、O、r和R中的某一个键即可,当进入编辑模式时,在屏幕的尾行显示INSERT字样(若支持中文,则显示插入)。按Esc键,从编辑模式回到一般模式。              i(小写) 从目前光标所在处插入。              I (大写)从目前光标所在处第一个非空格开始插入。              a 从光标所在处的下一个字符开始插入。              A 从光标所在处行的最后一个字符卡是插入
叶瑾
2018/06/14
1.6K0
Vim 模式
Vim和Vi一样具有三种模式:命令模式(Command mode),插入模式(Insert mode)和底线命令模式(Last line mode)。
Yif
2019/12/26
5580
Emacs 快捷键配置方案
Emacs 的快捷键和 Vim 的快捷键是编辑器中的两坐高山,其中 Emacs 的快捷键主要有四类。
zucchiniy
2020/05/22
1.2K0
Writer.com基于图的RAG向量检索替代方案
Writer 首席执行官 May Habib 说,其语义图形化方法是使用向量数据库对 RAG 进行区块划分过程的替代方案。
云云众生s
2024/03/28
2250
如何排查 Tramp 卡住问题
今天在进行一个操作时,突然出现了访问 tramp 的操作,最近有一段时间没有使用过,所以看到这个消息时比较好奇,是什么操作导致触发了 tramp。
飞驰的西瓜
2023/09/06
2150
如何排查 Tramp 卡住问题
onpropertychange替代方案[通俗易懂]
大家好,又见面了,我是你们的朋友全栈君。 onpropertychange替代方案
全栈程序员站长
2022/08/01
1.4K0
5个最受Linux程序员欢迎的代码编辑器
Linux程序员经常抱怨,自从他们使用了免费开源的系统平台后,作为一名程序员,却并没有在代码编辑器上得到足够的重视。他们往往会认为Linux平台上的代码编辑器太少了,以至于影响他们的编程工作。但是事实并非如此,在Linux平台上有太多的代码编辑器供你使用了,下面我们分享了5个最受Linux程序员欢迎的代码编辑器,继续在编程的路上前行吧!
CPP开发前沿
2022/06/04
1.1K0
5个最受Linux程序员欢迎的代码编辑器
Emacs 系列(一):抛掉一切,投入 Emacs 和 org 模式的怀抱
长期以来,我一直对如何组织安排事情感到沮丧。我也有用过 GTD 和 ZTD 之类的方法,但是像邮件或是大型文件这样的事务真的很难来组织安排。
用户1880875
2021/09/23
8460
Base:Acid的替代方案
作者:DAN PRITCHETT 译者:java达人 来源:https://queue.acm.org/detail.cfm?id=1394128(点击阅读原文前往) 在数据库分区中,以一致性换取可
java达人
2018/03/26
2.3K0
Base:Acid的替代方案
Hugo .GitInfo 的替代方案
今天有人问我博客页脚 footer 里的 git hash 是怎么显示的,就是页面底部里的 69d6ffe 这一串数字。
eallion
2022/12/20
1.9K0
Hugo .GitInfo 的替代方案
Web 框架的替代方案
在本系列第二部分中,Noam 提出了一些模式,说明如何直接用 Web 平台作为框架提供的一些解决方案的替代方案。
深度学习与Python
2022/04/19
2.6K0
进入编辑模式 , vim命令模式 , vim实践
所谓编辑模式就是进入可以编辑文件内容的状态,就和进入word文档进入记事本是一样的,最普遍进入编辑模式的方式就是按i,即进入当前光标所在位置的编辑模式。下面介绍几种进入编辑模式的方式:
端碗吹水
2020/09/23
2.2K0
进入编辑模式 , vim命令模式 , vim实践
Emacs 29.1 版本发布了
作为日常使用 Emacs 进行开发的重度用户,困扰笔者的一个问题时,同时打开多个项目时, xref 会错乱,这十分烦人,忍受一段时间后,最终去 SO 提问[2]了一下,Emacs 又一次没令我失望,29 里面已经有了解法:
飞驰的西瓜
2023/09/06
5790
Emacs 29.1 版本发布了
vim常用模式
# Vim的命令模式 使用 Vim 编辑文件时,默认处于命令模式。此模式下,可使用方向键(上、下、左、右键)或 k、j、h、i 移动光标的位置,还可以对文件内容进行复制、粘贴、替换、删除等操作。 # Vim的输入模式 在输入模式下,Vim 可以对文件执行写操作,类似于在 Windows 系统的文档中输入内容。 使 Vim 进行输入模式的方式是在命令模式状态下输入 i、I、a、A、o、O 等插入命令(各指令的具体功能如表 3 所示),当编辑文件完成后按 Esc 键即可返回命令模式。 # Vim 的编辑模式 编
summerking
2022/09/19
2610
探讨if...else的替代方案
假设我们要做一个计算器,实现加减乘除的需求。使用if...else...语句实现代码如下:
互联网金融打杂
2022/08/01
2.3K0
探讨if...else的替代方案
Flutter 中FlatButton的替代方案
最新版本的Flutter已将FlatButton标记为过时,我们可以使用 TextButton 或 ElevatedButton 来进行替代,FlatButton 与替代组件的参数会有差异。
xiangzhihong
2023/07/09
6710
Emacs 29快到了!我们能期待什么
几个小时前宣布,Emacs 29 的分支现在从 master 分支中切掉了!这意味着该emacs-29分支从现在起将不再接收任何新功能,而只会接收错误修复。
飞驰的西瓜
2022/12/14
2.6K0
Emacs 29快到了!我们能期待什么

相似问题

如何在vim中找到模式和替代

20

模式后的csplit拆分的替代方案。

10

不同的vim颜色方案取决于模式

10

基于USB的持久Debian系统Debian实况的替代方案

60

HUD的替代方案

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文