Как я могу переопределить тип поля DjangoModelFormMutation в графене? - PullRequest
2 голосов
/ 18 марта 2019

Я создаю простое приложение для хранения рецептов, которое использует пакет Graphene для GraphQL.До сих пор я мог очень легко использовать формы Django в своих мутациях, однако одно из полей моей модели - это действительно Enum, и я хотел бы представить его в Graphene / GraphQL как таковом.

Мой 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"

Моя модель:

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

Моя форма:

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

Моя мутация:

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

Я создалэто графеновое перечисление UnitEnum = Enum.from_enum(Unit) однако я не смог достать графен, чтобы взять его.Я попытался добавить его в CreateRecipeIngredientMutation как обычное поле, например unit = UnitEnum(), а также в класс Input для этой мутации.На данный момент самым близким, что я получил, является выпуск Github , сделанный некоторое время назад.После игры с классом в оболочке iPython, я думаю Я мог бы просто сделать CreateRecipeIngredientMutation.Input.unit.type.of_type = UnitEnum(), но это ужасно.

1 Ответ

0 голосов
/ 26 марта 2019

Я придумал решение, которое работает, но не красиво. Я использовал пакет https://github.com/hzdg/django-enumfields, чтобы помочь с этим.

Я создал собственное поле формы:

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)

И использовал это в моей форме Джанго. Затем в моем собственном 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)

И, наконец, в моей схеме:

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

Мне действительно не нравится это, но я не мог придумать лучшего способа справиться с этим. Я натолкнулся на эту идею, когда искал другую проблему с графеновым джанго здесь https://github.com/graphql-python/graphene-django/issues/481#issuecomment-412227036.

Я чувствую, что имеет , чтобы быть лучшим способом сделать это.

...