8.Mutations突变

Introduction 介绍

Graphene-Django makes it easy to perform mutations.

Graphene-Django使得进行突变变得容易。

With Graphene-Django we can take advantage of pre-existing Django features to quickly build CRUD functionality, while still using the core graphene mutation features to add custom mutations to a Django project.

使用Graphene-Django,我们可以利用已有的Django特性快速构建CRUD功能,同时仍然使用核心的graphene mutation特性向Django项目添加自定义突变。

Simple example 简单的例子

import graphene

from graphene_django import DjangoObjectType

from .models import Question


class QuestionType(DjangoObjectType):
    class Meta:
        model = Question


class QuestionMutation(graphene.Mutation):
    class Arguments:
        # The input arguments for this mutation
        # 此突变的输入参数
        text = graphene.String(required=True)
        id = graphene.ID()

    # The class attributes define the response of the mutation
    # 类属性定义了突变的响应
    question = graphene.Field(QuestionType)

    def mutate(self, info, text, id):
        question = Question.objects.get(pk=id)
        question.text = text
        question.save()
        # Notice we return an instance of this mutation
        # 注意,我们返回了这个突变的一个实例
        return QuestionMutation(question=question)


class Mutation(graphene.ObjectType):
    update_question = QuestionMutation.Field()

Django Forms Django表单

Graphene-Django comes with mutation classes that will convert the fields on Django forms into inputs on a mutation.

Graphene-Django附带了突变类,这些类将Django表单上的字段转换为突变时的输入。

DjangoFormMutation Django表单突变

from graphene_django.forms.mutation import DjangoFormMutation

class MyForm(forms.Form):
    name = forms.CharField()

class MyMutation(DjangoFormMutation):
    class Meta:
        form_class = MyForm

MyMutation will automatically receive an input argument. This argument should be a dict where the key is name and the value is a string.

MyMutation将自动接收input参数。这个参数应该是一个dict,其中键是name,值是一个字符串。

DjangoModelFormMutation Django模型表单突变

DjangoModelFormMutation will pull the fields from a ModelForm.

DjangoModelFormMutation将从ModelForm中提取字段。

from graphene_django.forms.mutation import DjangoModelFormMutation

class Pet(models.Model):
    name = models.CharField()

class PetForm(forms.ModelForm):
    class Meta:
        model = Pet
        fields = ('name',)

# This will get returned when the mutation completes successfully
# 当突变成功完成时,它将返回
class PetType(DjangoObjectType):
    class Meta:
        model = Pet

class PetMutation(DjangoModelFormMutation):
    pet = Field(PetType)

    class Meta:
        form_class = PetForm

PetMutation will grab the fields from PetForm and turn them into inputs. If the form is valid then the mutation will lookup the DjangoObjectType for the Pet model and return that under the key pet. Otherwise it will return a list of errors.

PetMutation将从PetForm中抓取字段并将它们转换为输入。如果表单是有效的,那么突变将查找DjangoObjectType用于Pet模型,并将其返回到Pet键下。否则,它将返回一个错误列表。

You can change the input name (default is input) and the return field name (default is the model name lowercase).

您可以更改输入名称(默认为input)和返回字段名称(默认为模型名称小写)。

class PetMutation(DjangoModelFormMutation):
    class Meta:
        form_class = PetForm
        input_field_name = 'data'
        return_field_name = 'my_pet'

Form validation 表单验证

Form mutations will call is_valid() on your forms.

表单突变会在表单上调用is_valid()

If the form is valid then the class method perform_mutate(form, info) is called on the mutation. Override this method to change how the form is saved or to return a different Graphene object type.

如果表单是有效的,那么类方法perform_mutate(form, info)就会被调用。重写此方法以更改表单的保存方式或返回不同的石墨烯对象类型。

If the form is not valid then a list of errors will be returned. These errors have two fields: field, a string containing the name of the invalid form field, and messages, a list of strings with the validation messages.

如果表单是无效的,那么一个错误列表将被返回。这些错误有两个字段:field,一个包含无效表单字段名称的字符串,和messages,一个包含验证消息的字符串列表。

Django REST Framework

You can re-use your Django Rest Framework serializer with Graphene Django mutations.

您可以使用Graphene Django突变重用Django Rest Framework序列化器。

You can create a Mutation based on a serializer by using the SerializerMutation base class:

你可以使用SerializerMutation基类创建一个基于序列化器的突变:

from graphene_django.rest_framework.mutation import SerializerMutation

class MyAwesomeMutation(SerializerMutation):
    class Meta:
        serializer_class = MySerializer

Create/Update Operations 创建/更新操作

By default ModelSerializers accept create and update operations. To customize this use the model_operations attribute on the SerializerMutation class.

默认情况下,模型序列化器接受创建和更新操作。要自定义这个属性,请使用SerializerMutation类上的model_operations属性。

The update operation looks up models by the primary key by default. You can customize the look up with the lookup_field attribute on the SerializerMutation class.

默认情况下,更新操作按主键查找模型。您可以使用SerializerMutation类上的lookup_field属性自定义查找。

from graphene_django.rest_framework.mutation import SerializerMutation
from .serializers import MyModelSerializer


class AwesomeModelMutation(SerializerMutation):
    class Meta:
        serializer_class = MyModelSerializer
        model_operations = ['create', 'update']
        lookup_field = 'id'

Overriding Update Queries 覆盖更新查询

Use the method get_serializer_kwargs to override how updates are applied.

使用方法get_serializer_kwargs来覆盖如何应用更新。

from graphene_django.rest_framework.mutation import SerializerMutation
from .serializers import MyModelSerializer


class AwesomeModelMutation(SerializerMutation):
    class Meta:
        serializer_class = MyModelSerializer

    @classmethod
    def get_serializer_kwargs(cls, root, info, **input):
        if 'id' in input:
            instance = Post.objects.filter(
                id=input['id'], owner=info.context.user
            ).first()
            if instance:
                return {'instance': instance, 'data': input, 'partial': True}

            else:
                raise http.Http404

        return {'data': input, 'partial': True}

Relay 中继

You can use relay with mutations. A Relay mutation must inherit from ClientIDMutation and implement the mutate_and_get_payload method:

你可以使用突变的中继。中继突变必须从ClientIDMutation继承并实现mutate_and_get_payload方法:

import graphene
from graphene import relay
from graphene_django import DjangoObjectType
from graphql_relay import from_global_id

from .queries import QuestionType


class QuestionMutation(relay.ClientIDMutation):
    class Input:
        text = graphene.String(required=True)
        id = graphene.ID()

    question = graphene.Field(QuestionType)

    @classmethod
    def mutate_and_get_payload(cls, root, info, text, id):
        question = Question.objects.get(pk=from_global_id(id)[1])
        question.text = text
        question.save()
        return QuestionMutation(question=question)

Notice that the class Arguments is renamed to class Input with relay. This is due to a deprecation of class Arguments in graphene 2.0.

注意,使用relay,“类参数”被重命名为“类输入”。这是由于在 graphene 2.0中不提倡“阶级争论”。

Relay ClientIDMutation accept a clientIDMutation argument. This argument is also sent back to the client with the mutation result (you do not have to do anything). For services that manage a pool of many GraphQL requests in bulk, the clientIDMutation allows you to match up a specific mutation with the response.

中继ClientIDMutation接受ClientIDMutation参数。这个参数也会连同突变结果一起发送回客户机(您不需要做任何事情)。对于批量管理许多GraphQL请求池的服务,clientIDMutation允许您将特定的突变与响应匹配。

posted @ 2020-09-25 07:10  双葫  阅读(302)  评论(0)    收藏  举报