简体   繁体   English

如何覆盖石墨烯中的DjangoModelFormMutation字段类型?

[英]How can I override a DjangoModelFormMutation field type in graphene?

I'm building a simple recipe storage application that uses the Graphene package for GraphQL. 我正在构建一个简单的配方存储应用程序,该应用程序将Graphene包用于GraphQL。 I've been able to use Django Forms so far very easily in my mutations, however one of my models fields is really an Enum and I'd like to expose it in Graphene/GraphQL as such. 到目前为止,我已经很容易在变体中使用Django Forms,但是我的模型字段之一实际上是一个Enum,我想在Graphene / GraphQL中公开它。

My enum: 我的列举:

class Unit(Enum):
    # Volume
    TEASPOON = "teaspoon"
    TABLESPOON = "tablespoon"
    FLUID_OUNCE = "fl oz"
    CUP = "cup"
    US_PINT = "us pint"
    IMPERIAL_PINT = "imperial pint"
    US_QUART = "us quart"
    IMPERIAL_QUART = "imperial quart"
    US_GALLON = "us gallon"
    IMPERIAL_GALLON = "imperial gallon"
    MILLILITER = "milliliter"
    LITER = "liter"

    # Mass and Weight
    POUND = "pound"
    OUNCE = "ounce"
    MILLIGRAM = "milligram"
    GRAM = "gram"
    KILOGRAM = "kilogram"

My Model: 我的模特:

class RecipeIngredient(TimeStampedModel):
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name='ingredients')
    direction = models.ForeignKey(RecipeDirection, on_delete=models.CASCADE, null=True, related_name='ingredients')

    quantity = models.DecimalField(decimal_places=2, max_digits=10)
    unit = models.TextField(choices=Unit.as_tuple_list())

My form: 我的表格:

class RecipeIngredientForm(forms.ModelForm):
    class Meta:
        model = RecipeIngredient
        fields = (
            'recipe',
            'direction',
            'quantity',
            'unit',
        )

My Mutation: 我的变异:

class CreateRecipeIngredientMutation(DjangoModelFormMutation):
    class Meta:
        form_class = RecipeIngredientForm
        exclude_fields = ('id',)

I've created this graphene enum UnitEnum = Enum.from_enum(Unit) however I haven't been able to get graphene to pick it up. 我已经创建了这个石墨烯枚举UnitEnum = Enum.from_enum(Unit)但是我还无法获得石墨烯来进行提取。 I've tried adding it to the CreateRecipeIngredientMutation as a regular field like unit = UnitEnum() as well as an Input class on that mutation. 我尝试将其作为常规字段(例如unit = UnitEnum()以及该突变的Input类添加到CreateRecipeIngredientMutation中。 So far, the closest I've gotten is this Github issue from awhile ago. 到目前为止,我得到的最接近的是前一段时间的Github问题 After playing around with the class in an iPython shell, I think I could just do CreateRecipeIngredientMutation.Input.unit.type.of_type = UnitEnum() but this feels awful. 在iPython shell中玩完该类之后,我我可以做CreateRecipeIngredientMutation.Input.unit.type.of_type = UnitEnum()但这感觉很糟糕。

I came up with a solution that works but is not pretty. 我想出了一个可行但不完美的解决方案。 I used the https://github.com/hzdg/django-enumfields package to help with this. 我使用了https://github.com/hzdg/django-enumfields包来帮助解决这个问题。

I created my own form field: 我创建了自己的表单字段:

class EnumChoiceField(enumfields.forms.EnumChoiceField):
    def __init__(self, enum, *, coerce=lambda val: val, empty_value='', **kwargs):
        if isinstance(enum, six.string_types):
            self.enum = import_string(enum)
        else:
            self.enum = enum

        super().__init__(coerce=coerce, empty_value=empty_value, **kwargs)

And used it in my Django form. 并以我的Django形式使用它。 Then in my custom AppConfig I did this: 然后在我的自定义AppConfig中,我这样做了:

class CoreAppConfig(AppConfig):
    name = 'myapp.core'

    def ready(self):
        registry = get_global_registry()

        @convert_form_field.register(EnumChoiceField)
        def convert_form_field_to_enum(field: EnumChoiceField):
            converted = registry.get_converted_field(field.enum)
            if converted is None:
                raise ImproperlyConfigured("Enum %r is not registered." % field.enum)
            return converted(description=field.help_text, required=field.required)

And finally in my schema: 最后是我的架构:

UnitEnum = Enum.from_enum(Unit)
get_global_registry().register_converted_field(Unit, UnitEnum)

I really don't like this, but couldn't think of a better way to handle this. 我真的不喜欢这样,但是想不出更好的方法来解决这个问题。 I came across this idea when searching down another graphene django issue here https://github.com/graphql-python/graphene-django/issues/481#issuecomment-412227036 . 当在此处https://github.com/graphql-python/graphene-django/issues/481#issuecomment-412227036搜索另一个石墨烯django问题时,我遇到了这个想法。

I feel like there has to be a better way to do this. 我觉得必须一个更好的方式来做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM