具有外键关系的对象在石墨烯中的 GraphQL 突变

GraphQL Mutation in Graphene for Object with Foreign Key Relation

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

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

create mutation 期望 IngredientInput 包括所有属性和外键关系的整数字段。所以 graphQL 突变本身目前可以按照我的意愿工作。

我的问题与 即使不一样也很相似,但这些答案对我没有帮助。

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
  }
}

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

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")

干杯!