【问题标题】:GraphQL Mutation in Graphene for Object with Foreign Key Relation具有外键关系的对象的石墨烯中的 GraphQL 突变
【发布时间】:2023-03-08 23:26:01
【问题描述】:

我正在使用 Python、GraphQL (graphene-django) 和 Django 构建一个简单的 CRUD 接口。包含与另一个对象 (Category) 的外键关系的对象 (Ingredient) 的 CREATE 突变将不起作用。我想为 GraphQL 提供 CategoryObject 的 ID,而不是整个类别实例。然后在后端它应该绘制与 Category 对象的关系。

在 Django 模型中,成分对象包含外键类别对象的一个​​实例(参见下面的代码)。此处是否需要整个类别对象来绘制关系并使用Ingredient.objects.select_related('category').all()

创建突变需要IngredientInput,其中包括所有属性和外键关系的整数字段。因此,graphQL 突变本身目前可以按我的意愿工作。

我的问题与this one 类似,但这些答案对我没有帮助。

models.py:

class Category(models.Model):
    name = models.CharField(max_length=50, unique=True)
    notes = models.TextField()

    class Meta:
        verbose_name = u"Category"
        verbose_name_plural = u"Categories"
        ordering = ("id",)

    def __str__(self):
        return self.name


class Ingredient(models.Model):
    name = models.CharField(max_length=100)
    notes = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    class Meta:
        verbose_name = u"Ingredient"
        verbose_name_plural = u"Ingredients"
        ordering = ("id",)

    def __str__(self):
        return self.name

schema.py:

class CategoryType(DjangoObjectType):
    class Meta:
        model = Category


class CategoryInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    notes = graphene.String()


class IngredientType(DjangoObjectType):
    class Meta:
        model = Ingredient


class IngredientInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    notes = graphene.String()
    category = graphene.Int()


class CreateIngredient(graphene.Mutation):
    class Arguments:
        ingredientData = IngredientInput(required=True)

    ingredient = graphene.Field(IngredientType)

    @staticmethod
    def mutate(root, info, ingredientData):
        _ingredient = Ingredient.objects.create(**ingredientData)
        return CreateIngredient(ingredient=_ingredient)


class Mutation(graphene.ObjectType):
    create_category = CreateCategory.Field()
    create_ingredient = CreateIngredient.Field()

graphql_query:

mutation createIngredient($ingredientData: IngredientInput!) {
  createIngredient(ingredientData: $ingredientData) {
    ingredient {
      id
      name
      notes
      category{name}
    }

graphql 变量:

{
  "ingredientData": {
    "name": "milk",
    "notes": "from cow",
    "category": 8  # here I ant to insert the id of an existing category object
  }
}

执行查询后的错误信息:

{
  "errors": [
    {
      "message": "Cannot assign \"8\": \"Ingredient.category\" must be a \"Category\" instance.",
      "locations": [
        {
          "line": 38,
          "column": 3
        }
      ],
      "path": [
        "createIngredient"
      ]
    }
  ],
  "data": {
    "createIngredient": null
  }
}

【问题讨论】:

    标签: python django graphql graphene-django


    【解决方案1】:

    我今天也遇到了同样的问题。

    Cannot assign \"8\": \"Ingredient.category\" must be a \"Category\" instance. 错误是当您尝试直接使用外键整数而不是对象创建对象时发生的 Django 错误。 如果要直接使用外键ID,则必须使用_id 后缀。

    例如,而不是使用:

    _ingredient = Ingredient.objects.create(name="milk", notes="from_cow", category=8)
    

    你必须使用任何一个

    category_obj = Category.objects.get(id=8)
    _ingredient = Ingredient.objects.create(name="milk", notes="from_cow", category=category_obj)
    

    _ingredient = Ingredient.objects.create(name="milk", notes="from_cow", category_id=8)
    

    在使用 GraphQL 的情况下,您必须将 InputObjectType 字段设置为 _id。在你的情况下:

    class IngredientInput(graphene.InputObjectType):
        name = graphene.String(required=True)
        notes = graphene.String()
        category_id = graphene.Int()
    

    但是,这会使架构中的字段显示为categoryId。如果您希望保留 category 名称,您必须更改为:

    category_id = graphene.Int(name="category")
    

    干杯!

    【讨论】:

    • 感谢您提供非常有用且详细的回答!
    • 这正是我想要的!我希望这是最好的做法!
    猜你喜欢
    • 2022-01-17
    • 2020-09-19
    • 2020-09-01
    • 2017-03-18
    • 2017-05-11
    • 2017-05-13
    • 2020-05-03
    • 2021-12-02
    • 2021-12-17
    相关资源
    最近更新 更多