【问题标题】:How can I use a single enum for django model and graphql mutation arguments?如何将单个枚举用于 django 模型和 graphql 突变参数?
【发布时间】:2020-07-15 17:58:30
【问题描述】:

我已经定义了 Django 模型,其字段包含对应于枚举的文本选择。 GraphQL API 提供了带有 enum 类型参数的突变(不是直接从模型派生的),它应该只接受与模型相同的值。我怎样才能摆脱我的重复?

models.py:

class SomeModel(models.Model):

    class SomeEnum(models.TextChoices):

        A = "A", _("Option A")
        B = "B", _("Option B")

    enum_field = models.CharField(
        max_length=1,
        choices=SomeEnum.choices,
        default=SomeEnum.A,
    )

schema.py:


class SomeEnumSchema(graphene.Enum):

    A = "A"
    B = "B"


class SomeMutation(graphene.Mutation):

    class Arguments:
        some_enum = SomeEnumSchema(required=True)

【问题讨论】:

  • 我不知道 python ... 将值提取到某个基类,两者都通用 - 多重继承?

标签: python django django-models graphql graphene-django


【解决方案1】:

使用以下类扩展您的 graphene.Enum 实例

from inspect import getmembers, isroutine

class EnumChoices:
    @classmethod
    def choices(self):
        attributes = getmembers(self, lambda a: not (isroutine(a)))
        values = [(a[0], a[1]._value_) for a in attributes if hasattr(a[1], "_value_")]
        return values

您的示例枚举将如下所示

# import the EnumChoices class above 
from graphene import Enum

class YourExampleChoices(EnumChoices, Enum):
    BAD = "Bad"
    MEH = "Meh"
    NORMAL = "Normal"
    LIKE = "Like"
    LOVE = "Love"

您的示例 graphene.types.InputObjectType 将如下所示

# import the YourExampleChoices class above
from graphene.types import InputObjectType

class YourExampleChoicesMutationInput(InputObjectType):
    choice = YourExampleChoices(required=True)

您的示例 graphene.Mutation 将如下所示

# import the YourExampleChoicesMutationInput class above 
import graphene

from graphene.types.mutation import Mutation

class YourExampleMutation(Mutation):
    # make sure to define your mutation results fields

    class Arguments:
        input = YourExampleChoicesMutationInput(required=True)

    def mutate(root, info, input):
        # what do you want this mutation to do?
        pass

您的 Django 模型将如下所示

# import the YourExampleChoices class above
# notice that `YourExampleChoices.choices()` is callable, this is slightly different from the `Textchoices.choices` which isn't callable

class YourExampleModel(TimestampBase):
    choices = models.CharField(
        max_length=6, 
        choices=YourExampleChoices.choices(), 
        default=YourExampleChoices.NORMAL._value_
    )

【讨论】:

    【解决方案2】:

    如果您想在自定义突变中使用 Enums,您可以像这样使用graphine.Enum。

    class PermisionEnum(graphene.Enum):
        READ = "read"
        WRITE = "write"
    
    
    class SimpleModelMutation(graphene.Mutation):
    
        class Arguments:
            # reusable
            permission = PermisionEnum(required=True)
            # not reusable
            scope = graphene.Enum('scope', [
                ("PERSONAL", "personal"),
                ("PROJECT", "project")
            ])(required=True)
    

    我建议使用PermisionEnum(required=True) 方法,因为使用它PermisionEnum 类可以在不同的突变中重复使用。当您声明枚举时,这是不可能的,因为我使用 scope 归档!

    【讨论】:

      【解决方案3】:

      您可以使用graphene.Enum.from_enum()。

      该函数可以将普通的Enum类型转换为graphene.Enum。

      请注意models.TextChoices 仅适用于 3.0 以上的 Dajango 版本

      models.py(对于 Django 版本 >= 3.0)

      from django.db import models
      
      class SomeModel(models.Model):
      
          class SomeEnum(models.TextChoices):
      
              A = "A", _("Option A")
              B = "B", _("Option B")
      
          enum_field = models.CharField(
              max_length=1,
              choices=SomeEnum.choices,
              default=SomeEnum.A,
          )
      

      models.py(适用于 Django 版本

      from enum import Enum
      class SomeEnum(Enum):
          A = "A"
          B = "B"
      

      schema.py:

      SomeEnumSchema = graphene.Enum.from_enum(SomeEnum)
      class SomeMutation(graphene.Mutation):
          class Arguments:
              some_enum = SomeEnumSchema(required=True)
      

      【讨论】:

      • 对于 Django >= 3.0 版本的一个重要说明是每个枚举选项的类变量名称必须匹配元组的第一个元素。这意味着要使用 Option A 枚举的小写键,它必须写为 a = "a", _("Option A")
      猜你喜欢
      • 2018-11-21
      • 2018-05-22
      • 2019-08-31
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多