Package: graphene-django-crud
Graphene-Django-CrudInspired by prisma-nexus and graphene-django-extras, this package transforms the
django orm into a graphql API with the following features:Expose CRUD opérationsOptimized querysetFiltering with logical operatorsAuthentication and permissionsNested mutationsTable of contentsGraphene-Django-CrudTable of contentsInstallationInstall with pipInstall with source codeUsageExampleComputed FieldUser permissionsFiltering by userUse with relayExtend ConnectionTypeUse list fieldExtend ConnectionType without RelayExtend ConnectionType with RelayDjangoCRUDObjectType ClassMeta parametersmodelmax_limitonly_fields / exclude_fieldsinput_only_fields / input_exclude_fieldscreate_only_fields / create_exclude_fieldsupdate_only_fields / update_exclude_fieldsinput_extend_fieldswhere_only_fields / where_exclude_fieldsorder_by_only_fields / order_by_exclude_fieldscreate_mutation / update_mutation / delete_mutationvalidatorvalidator_excludevalidator_validate_uniqueGraphene FieldsReadFieldBatchReadFieldCreateFieldUpdateFieldDeleteFieldInput TypesWhereInputTypeOrderByInputTypeCreateInputTypeUpdateInputTypeMethods to overrideget_queryset(cls, parent, info, **kwargs)mutate, create, update, delete(Deprecated) Middleware methods before_XXX(cls, parent, info, instance, data) / after_XXX(cls, parent, info, instance, data)SettingsCustomizeDEFAULT_CONNECTION_NODES_FIELD_NAMEFILE_TYPE_CONTENT_FIELD_ACTIVECONVERT_ENUM_FIELDSCompatibility with old versionSCALAR_FILTERS_ADD_EQUALS_FIELDBOOLEAN_FILTER_USE_BOOLEAN_FIELDUtils@resolver_hints(only: list[str], select_related:list[str])where_input_to_Q(where_input: dict) -> Qorder_by_input_to_args(order_by_input: list[dict]) -> list[str]Schema generatedFields MappingModel mutation / query fieldsModel typesFileFileInputBinaryOrderEnumScalar filtersInstallationFor the support ofMultipart Request Spec,
installgraphene-file-uploadaccording to the documentation.Install with pipTo install graphene-django-crud, simply run this simple command in your terminal
of choice:$ pip install graphene-django-crudInstall with source codegraphene-django-crud is developed on GitHub, You can either clone the public
repository:$ git clone https://github.com/djipidi/graphene_django_crud.gitOnce you have a copy of the source, you can embed it in your own Python package,
or install it into your site-packages easily:$ cd graphene_django_crud
$ python setup.py installUsageThe DjangoCRUDObjectType class project a django model into a graphene type. The
type has fields to exposes the CRUD operations.ExampleIn this example, you will be able to project the auth django models on your
GraphQL API and expose the CRUD operations.# schema.pyimportgraphenefromgraphqlimportGraphQLErrorfromdjango.contrib.auth.modelsimportUser,Groupfromgraphene_django_crud.typesimportDjangoCRUDObjectType,resolver_hintsclassUserType(DjangoCRUDObjectType):classMeta:model=Userexclude_fields=("password",)input_exclude_fields=("last_login","date_joined")full_name=graphene.String()@resolver_hints(only=["first_name","last_name"])@staticmethoddefresolve_full_name(parent,info,**kwargs):returnparent.get_full_name()@classmethoddefget_queryset(cls,parent,info,**kwargs):ifinfo.context.user.is_authenticated:returnUser.objects.all()else:returnUser.objects.none()@classmethoddefmutate(cls,parent,info,instance,data,*args,**kwargs):ifnotinfo.context.user.is_staff:raiseGraphQLError('not permited, only staff user')if"password"indata.keys():instance.set_password(data.pop("password"))returnsuper().mutate(parent,info,instance,data,*args,**kwargs)classGroupType(DjangoCRUDObjectType):classMeta:model=GroupclassQuery(graphene.ObjectType):me=graphene.Field(UserType)user=UserType.ReadField()users=UserType.BatchReadField()group=GroupType.ReadField()groups=GroupType.BatchReadField()defresolve_me(parent,info,**kwargs):ifnotinfo.context.user.is_authenticated:returnNoneelse:returninfo.context.userclassMutation(graphene.ObjectType):user_create=UserType.CreateField()user_update=UserType.UpdateField()user_delete=UserType.DeleteField()group_create=GroupType.CreateField()group_update=GroupType.UpdateField()group_delete=GroupType.DeleteField()And get the resulting GraphQL API:toggle meschema {
  query: Query
  mutation: Mutation
}

scalar DateTime

input DatetimeFilter {
  equals: DateTime
  exact: DateTime
  in: [DateTime]
  isnull: Boolean
  gt: DateTime
  gte: DateTime
  lt: DateTime
  lte: DateTime
  year: IntFilter
  month: IntFilter
  day: IntFilter
  weekDay: IntFilter
  hour: IntFilter
  minute: IntFilter
  second: IntFilter
}

type ErrorType {
  field: String!
  messages: [String!]!
}

input GroupCreateInput {
  name: String!
  userSet: UserCreateNestedManyInput
}

input GroupCreateNestedManyInput {
  create: [GroupCreateInput]
  connect: [GroupWhereInput]
}

input GroupOrderByInput {
  id: OrderEnum
  name: OrderStringEnum
}

type GroupType {
  id: ID
  name: String
  userSet(where: UserWhereInput, orderBy: [UserOrderByInput], limit: Int, offset: Int): UserConnection
}

type GroupConnection {
  data: [GroupType]!
  count: Int
}

type GroupCreatePayload {
  ok: Boolean
  errors: [ErrorType]
  result: GroupType
}

type GroupUpdatePayload {
  ok: Boolean
  errors: [ErrorType]
  result: GroupType
}
type GroupDeletePayload {
  ok: Boolean
  errors: [ErrorType]
}

input GroupUpdateInput {
  name: String
  userSet: UserUpdateNestedManyInput
}

input GroupUpdateNestedManyInput {
  create: [GroupCreateInput]
  delete: [GroupWhereInput]
  connect: [GroupWhereInput]
  disconnect: [GroupWhereInput]
}

input GroupWhereInput {
  id: IdFilter
  name: StringFilter
  user: UserWhereInput
  OR: [GroupWhereInput]
  AND: [GroupWhereInput]
  NOT: GroupWhereInput
}

input IdFilter {
  equals: ID
  exact: ID
  in: [ID]
  isnull: Boolean
}

input IntFilter {
  equals: Int
  exact: Int
  in: [Int]
  isnull: Boolean
  gt: Int
  gte: Int
  lt: Int
  lte: Int
  contains: Int
  startswith: Int
  endswith: Int
  regex: String
}

type Mutation {
  userCreate(input: UserCreateInput!): UserCreatePayload
  userUpdate(input: UserUpdateInput!, where: UserWhereInput!): UserUpdatePayload
  userDelete(where: UserWhereInput!): UserDeletePayload
  groupCreate(input: GroupCreateInput!): GroupCreatePayload
  groupUpdate(input: GroupUpdateInput!, where: GroupWhereInput!): GroupUpdatePayload
  groupDelete(where: GroupWhereInput!): GroupDeletePayload
}

enum OrderEnum {
  ASC
  DESC
}

enum OrderStringEnum {
  ASC
  DESC
}

type Query {
  me: UserType
  user(where: UserWhereInput!): UserType
  users(where: UserWhereInput, orderBy: [UserOrderByInput], limit: Int, offset: Int): UserConnection
  group(where: GroupWhereInput!): GroupType
  groups(where: GroupWhereInput, orderBy: [GroupOrderByInput], limit: Int, offset: Int): GroupConnection
}

input StringFilter {
  equals: String
  exact: String
  in: [String]
  isnull: Boolean
  contains: String
  startswith: String
  endswith: String
  regex: String
  iexact: String
  icontains: String
  istartswith: String
  iendswith: String
}

input UserCreateInput {
  email: String
  firstName: String
  groups: GroupCreateNestedManyInput
  isActive: Boolean
  isStaff: Boolean
  isSuperuser: Boolean
  lastName: String
  password: String!
  username: String!
}

input UserCreateNestedManyInput {
  create: [UserCreateInput]
  connect: [UserWhereInput]
}

input UserOrderByInput {
  dateJoined: OrderEnum
  email: OrderStringEnum
  firstName: OrderStringEnum
  id: OrderEnum
  isActive: OrderEnum
  isStaff: OrderEnum
  isSuperuser: OrderEnum
  lastLogin: OrderEnum
  lastName: OrderStringEnum
  username: OrderStringEnum
}

type UserType {
  id: ID
  dateJoined: DateTime
  email: String
  firstName: String
  groups(where: GroupWhereInput, orderBy: [GroupOrderByInput], limit: Int, offset: Int): GroupConnection
  isActive: Boolean
  isStaff: Boolean
  isSuperuser: Boolean
  lastLogin: DateTime
  lastName: String
  username: String
  fullName: String
}

type UserConnection {
  data: [UserType]!
  count: Int
}

type UserCreatePayload {
  ok: Boolean
  errors: [ErrorType]
  result: UserType
}

type UserUpdatePayload {
  ok: Boolean
  errors: [ErrorType]
  result: UserType
}

type UserDeletePayload {
  ok: Boolean
  errors: [ErrorType]
}

input UserUpdateInput {
  email: String
  firstName: String
  groups: GroupUpdateNestedManyInput
  isActive: Boolean
  isStaff: Boolean
  isSuperuser: Boolean
  lastName: String
  password: String
  username: String
}

input UserUpdateNestedManyInput {
  create: [UserCreateInput]
  delete: [UserWhereInput]
  connect: [UserWhereInput]
  disconnect: [UserWhereInput]
}

input UserWhereInput {
  id: IdFilter
  dateJoined: DatetimeFilter
  email: StringFilter
  firstName: StringFilter
  groups: GroupWhereInput
  isActive: Boolean
  isStaff: Boolean
  isSuperuser: Boolean
  lastLogin: DatetimeFilter
  lastName: StringFilter
  username: StringFilter
  OR: [UserWhereInput]
  AND: [UserWhereInput]
  NOT: UserWhereInput
}Queries example:query{
  user(where: {id: {equals:1}}){
    id
    username
    firstName
    lastName
  }
}


query{
  users(
    where: {
      OR: [
        {isStaff: true},
        {isSuperuser: true},
        {groups: {name: {equals: "admin"}}},
      ]
    }
    orderBy: [{username: ASC}],
    limit: 100,
    offset: 0
  ){
    count
    data{
      id
      username
      firstName
      lastName
      groups{
        count
        data{
          id
          name
        }
      }
    }
  }
}

mutation{
  groupCreate(
    input: {
      name: "admin",
      userSet: {
        create: [
          {username: "woody", password: "raC4RjDU"},
        ],
        connect: [
          {id: {equals: 1}}
        ]
      },
    }
  ){
    ok
    result{
      id
      name
      userSet{
        count
        data{
          id
          username
        }
      }
    }
  }
}Computed FieldYou can add computed fields using the standard Graphene API. However to optimize
the SQL query you must specify "only", "select_related" necessary for the
resolver using the resolver_hints decoratorclassUserType(DjangoCRUDObjectType):classMeta:model=Userfull_name=graphene.String()@resolver_hints(only=["first_name","last_name"])@staticmethoddefresolve_full_name(parent,info,**kwargs):returnparent.get_full_name()User permissionsThe methods mutate, create, update, deleteare
called for each change of model instances during mutations and nested mutations.
They can be used to check permissions.classUserType(DjangoCRUDObjectType):classMeta:model=User@classmethoddefmutate(cls,parent,info,instance,data,*args,**kwargs):ifnotinfo.context.user.is_authenticated:raiseGraphQLError('not authorized, you must be logged in')returnsuper().mutate(parent,info,instance,data,*args,**kwargs)@classmethoddefcreate(cls,parent,info,instance,data,*args,**kwargs):ifnotinfo.context.user.has_perm("add_user"):raiseGraphQLError('not authorized, you must have add_user permission')returnsuper().create(parent,info,instance,data,*args,**kwargs)@classmethoddefupdate(cls,parent,info,instance,data,*args,**kwargs):ifnotinfo.context.user.has_perm("change_user"):raiseGraphQLError('not authorized, you must have change_user permission')returnsuper().update(parent,info,instance,data,*args,**kwargs)@classmethoddefdelete(cls,parent,info,instance,data,*args,**kwargs):ifnotinfo.context.user.has_perm("delete_user"):raiseGraphQLError('not authorized, you must have delete_user permission')returnsuper().delete(parent,info,instance,data,*args,**kwargs)Filtering by userTo filter based on the authenticated user, overload the get_queryset method as
the exampleclassUserType(DjangoCRUDObjectType):classMeta:model=User@classmethoddefget_queryset(cls,parent,info,**kwargs):ifinfo.context.user.is_authenticated:returnUser.objects.all()else:returnUser.objects.none()Use with relayThe configuration is the same as graphene-django, just add the "relay.Node"
interface.classCategoryType(DjangoCRUDObjectType):classMeta:model=Categoryinterfaces=(relay.Node,)classIngredientType(DjangoCRUDObjectType):classMeta:model=Ingredientinterfaces=(relay.Node,)classQuery(graphene.ObjectType):node=relay.Node.Field()category=CategoryType.ReadField()all_categories=CategoryType.BatchReadField()ingredient=IngredientType.ReadField()all_ingredients=IngredientType.BatchReadField()Relay.global_id as well as model id are supported to write the query using the
"id" field of whereInputType.Extend ConnectionTypeBy default, graphene_django_crud creates a connection type for the bachread
request and the many_to_many/many_to_one relationships.the default connection has a "count" field returning the count() value of the
queryset and a data field returning the results of the queryset.Use list fieldfrom.modelsimportProductimportgraphenefromgraphene_django_crudimportDjangoCRUDObjectTypeclassProductType(DjangoCRUDObjectType):classMeta:model=Productuse_connection=FalseExtend ConnectionType without Relayfrom.modelsimportProductfromdjango.db.modelsimportAvgimportgraphenefromgraphene_django_crudimportDefaultConnection,DjangoCRUDObjectTypeclassConnectionWithPriceAVG(DefaultConnection):classMeta:abstract=Trueprice_avg=graphene.Float()defresolve_price_avg(self,info):returnself.iterable.aggregate(Avg('price'))["price__avg"]classProductType(DjangoCRUDObjectType):classMeta:model=Productconnection_class=ConnectionWithPriceAVGExtend ConnectionType with Relayfrom.modelsimportProductimportgraphenefromgraphene_django_crudimportDjangoCRUDObjectTypeclassConnectionWithTotalCount(graphene.Connection):classMeta:abstract=Truetotal_count=graphene.Int()defresolve_total_count(self,info):returnself.iterable.count()classProductType(DjangoCRUDObjectType):classMeta:model=Productinterfaces=(relay.Node,)connection_class=ConnectionWithTotalCountDjangoCRUDObjectType ClassFrom the version v1.3.0,DjangoGrapheneCRUDclass has been renamed toDjangoCRUDObjectType, so the name "DjangoGrapheneCRUD" is deprecated.Meta parametersmodelRequired parameterThe model used for the definition typemax_limitdefault :NoneTo avoid too large transfers, the max_limit parameter imposes
a maximum number of return items for batchreadField and nodeField. it imposes to
use pagination. If the value isNonethere is no limit.only_fields / exclude_fieldsTuple of model fields to include/exclude in graphql type. Only one of the two
parameters can be declared.input_only_fields / input_exclude_fieldsTuple of model fields to include/exclude in graphql create and update inputs
type. Only one of the two parameters can be declared.create_only_fields / create_exclude_fieldsTuple of model fields to include/exclude in graphql create inputs
type. Only one of the two parameters can be declared.update_only_fields / update_exclude_fieldsTuple of model fields to include/exclude in graphql update inputs
type. Only one of the two parameters can be declared.input_extend_fieldsField list to extend the create and update inputs. value must be a list of tuple
(name: string, type: graphene.ObjectType). The parameters can be processed with
methodsmutate, create, update, deleteexample:classUserType(DjangoCRUDObjectType):classMeta:model=Userinput_extend_fields=(("fullName",graphene.String()),)@classmethoddefmutate(cls,parent,info,instance,data,*args,**kwargs):if"fullName"indata.keys():instance.first_name=data["fullName"].split(" ")[0]instance.last_name=data["fullName"].split(" ")[1]returnsuper().mutate(parent,info,instance,data,*args,**kwargs)where_only_fields / where_exclude_fieldsTuple of model fields to include/exclude in graphql where input type. Only one
of the two parameters can be declared.order_by_only_fields / order_by_exclude_fieldsTuple of model fields to include/exclude in graphql order_by input type. Only
one of the two parameters can be declared.create_mutation / update_mutation / delete_mutationdefault: TrueActivate/deactivate the nested mutation.validatordefault: TrueActivate/deactivate the validation of the model. if the value is
True, full_clean() method of model will be called before save().validator_excludedefault: NoneThe exclude argument of full_clean() method.validator_validate_uniquedefault: TrueThe validate_unique argument of full_clean() method.Graphene FieldsThe DjangoCRUDObjectType class contains configurable operation publishers that
you use for exposing create, read, update, and delete mutations against your
projected modelsfor mutating, relation fields may be connected with an existing record or a
sub-create may be inlined (generally referred to as nested mutations). If the
relation is a List then multiple connections or sub-creates are permitted.Inlined mutations are very similar to top-level ones but have the important
difference that the sub-create has excluded the field where supplying its
relation to the type of parent Object being created would normally be. This is
because a sub-create forces its record to relate to the parent one.Warning: By default, mutations are not atomic, specifyATOMIC_REQUESTSorATOMIC_MUTATIONSon True in your setting.pySee:Transaction with graphene-djangoReadFieldQuery field to allow clients to find one particular record at time of the
respective model.BatchReadFieldQuery field to allow clients to fetch multiple records at once of the respective
model.CreateFieldMutation field to allow clients to create one record at time of the respective
model.UpdateFieldMutation field to allow clients to update one particular record at time of the
respective model.DeleteFieldMutation field to allow clients to delete one particular record at time of the
respective model.Input TypesWhereInputTypeInput type composed ofthe scalar filtersof each readable
fields of the model. The logical operators "OR", "AND", "NO" are also included.
the returned arg can be used in queryset with functionwhere_input_to_QOrderByInputTypeInput type composed of the orderByEnum of each readable fields of the model.CreateInputTypeInput type composed of model fields without the id. If the field is not
nullable, the graphene field is required.UpdateInputTypeInput type composed of each fields of the model. No fields are required.Methods to overrideget_queryset(cls, parent, info, **kwargs)@classmethoddefget_queryset(cls,parent,info,**kwargs):returnqueryset_classDefault it returns "model.objects.all()", the overload is useful for applying
filtering based on user. The method is called in nested request, fetch instances
for mutations and subscription filter.mutate, create, update, deleteMethods called for each mutation and nested mutation impacting the model.
Overload this method to add preprocessing and / or overprocessing. The mutate
method is called before the create, update, delete methods. The "data" argument
is a dict corresponding to the graphql input argument.@classmethoddefmutate(cls,parent,info,instance,data,*args,**kwargs):# code before save instanceinstance=super().mutate(cls,parent,info,instance,data,*args,**kwargs)# code after save instancereturninstance@classmethoddefcreate(cls,parent,info,instance,data,*args,**kwargs):# code before save instanceinstance=super().create(cls,parent,info,instance,data,*args,**kwargs)# code after save instancereturninstance@classmethoddefupdate(cls,parent,info,instance,data,*args,**kwargs):# code before save instanceinstance=super().update(cls,parent,info,instance,data,*args,**kwargs)# code after save instancereturninstance@classmethoddefdelete(cls,parent,info,instance,data,*args,**kwargs):# code before save instanceinstance=super().delete(cls,parent,info,instance,data,*args,**kwargs)# code after save instancereturninstance(Deprecated) Middleware methods before_XXX(cls, parent, info, instance, data) / after_XXX(cls, parent, info, instance, data)from the version v1.3.0, these methods are deprecated, use the methodsmutate, create, update, delete@classmethoddefbefore_mutate(cls,parent,info,instance,data):pass@classmethoddefbefore_create(cls,parent,info,instance,data):pass@classmethoddefbefore_update(cls,parent,info,instance,data):pass@classmethoddefbefore_delete(cls,parent,info,instance,data):pass@classmethoddefafter_mutate(cls,parent,info,instance,data):pass@classmethoddefafter_create(cls,parent,info,instance,data):pass@classmethoddefafter_update(cls,parent,info,instance,data):pass@classmethoddefafter_delete(cls,parent,info,instance,data):passMethods called before or after a mutation. The "instance" argument is the
instance of the model that goes or has been modified retrieved from the "where"
argument of the mutation, or it's been created by the model constructor. The
"data" argument is a dict of the "input" argument of the mutation. The method is
also called in nested mutation.SettingsGraphene-django-crud reads your configuration from a single Django setting named
GRAPHENE_DJANGO_CRUD:GRAPHENE_DJANGO_CRUD={"DEFAULT_CONNECTION_NODES_FIELD_NAME":"nodes"}Here’s a list of settings available in graphene-django-crud and their default
values:CustomizeDEFAULT_CONNECTION_NODES_FIELD_NAMEName of node field in connection field.Default:'data'FILE_TYPE_CONTENT_FIELD_ACTIVEAdd a content field with the content of the file. The type used is
Binary.Default:FalseCONVERT_ENUM_FIELDSEnables / disables converting fields with choices to enum fields.Default:TrueCompatibility with old versionSCALAR_FILTERS_ADD_EQUALS_FIELDFrom version 1.3.0 the "equals" field of all scalar filters has been renamed to
"exact". To keep the client compatible we can add it by set the parameter toTrue.Default:FalseBOOLEAN_FILTER_USE_BOOLEAN_FIELDFrom version 1.3.0 the filter boolean is like the other scalar filters. To keep
the client compatible we can add it by set the parameter toTrue.Default:FalseUtils@resolver_hints(only: list[str], select_related:list[str])Each query uses "only", "select_related" and "prefetch_related" methods of
queryset to get only the necessary attributes. To extend fields, the decorator
is necessary for the queryset builder with its arguments which model attributes
are needed to resolve the field.showComputed fieldsection for more informationswhere_input_to_Q(where_input: dict) -> QIn order to be able to reuse where input generated, the where_input_to_Q
function transforms the returned argument into a Q objectexample :<model>.objects.filter(where_input_to_Q(where))order_by_input_to_args(order_by_input: list[dict]) -> list[str]In order to be able to reuse order_by input generated, the
order_by_input_to_args function transforms the returned argument into args for
order_by method of queryset.example :<model>.objects.all().order_by(*order_by_input_to_args(order_by))Schema generatedDjangoCRUDObjectType Classcontains configurable
fields that you use for projecting fields of your django model onto graphql objects.Fields MappingModel field<model>Type<model>WhereInput<model>CreateInput<model>UpdateInput<model>orderByInputAutoFieldIDIDFilterIDIDOrderEnumBigAutoFieldIDIDFilterIDIDOrderEnumUUIDFieldUUIDUUIDFilterUUIDUUIDOrderEnumCharFieldStringStringFilterStringStringOrderStringEnumTextFieldStringStringFilterStringStringOrderStringEnumEmailFieldStringStringFilterStringStringOrderStringEnumSlugFieldStringStringFilterStringStringOrderStringEnumURLFieldStringStringFilterStringStringOrderStringEnumGenericIPAddressFieldStringStringFilterStringStringOrderStringEnumPositiveIntegerFieldIntIntFilterIntIntOrderEnumPositiveSmallIntegerFieldIntIntFilterIntIntOrderEnumSmallIntegerFieldIntIntFilterIntIntOrderEnumBigIntegerFieldIntIntFilterIntIntOrderEnumIntegerFieldIntIntFilterIntIntOrderEnumBooleanFieldBooleanBooleanFilterBooleanBooleanOrderEnumBinaryFieldBinaryBinaryBinaryDecimalFieldFloatFloatFilterFloatFloatOrderEnumFloatFieldFloatFloatFilterFloatFloatOrderEnumDurationFieldFloatFloatFilterFloatFloatOrderEnumDateFieldDateDateFilterDateDateOrderEnumDateTimeFieldDateTimeDatetimeFilterDateTimeDateTimeOrderEnumTimeFieldTimeTimeFilterTimeTimeOrderEnumFileFieldFileStringFilterFileInputFileInputOrderEnumImageFieldFileStringFilterFileInputFileInputOrderEnumForeignKey<model>Type<model>WhereInput<model>CreateNestedInput<model>UpdateNestedInput<model>OrderByInputManyToOneRel<model>Connection<model>WhereInput<model>CreateNestedManyInput<model>UpdateNestedManyInputOneToOneField<model>Type<model>WhereInput<model>CreateNestedInput<model>UpdateNestedInput<model>OrderByInputOneToOneRel<model>Type<model>WhereInput<model>CreateNestedInput<model>UpdateNestedInput<model>OrderByInputManyToManyField<model>Connection<model>WhereInput<model>CreateNestedManyInput<model>UpdateNestedManyInputManyToManyRel<model>Connection<model>WhereInput<model>CreateNestedManyInput<model>UpdateNestedManyInputModel mutation / query fieldsquery {
  <model>(where: <model>CreateInput!): <model>Type
  <model_plural_name>(
    where: <model>CreateInput
    orderBy: [<model>orderByInput]
    limit: Int
    offset: Int
  ): <model>Connection
}

mutation {
  <model>Create(input: <model>CreateInput!): <model>CreatePayload
  <model>Update(input: <model>UpdateInput!, where: <model>UpdateInput!): <model>UpdatePayload
  <model>Delete(where: <model>CreateInput!): <model>DeletePayload
}Model typestype <model>Type {
  ...<fields Mapping>
}

type <model>Connection {
  data: [<modelType>]
  count: Int
}

type <model>CreatePayload {
  ok: Boolean
  errors: [errorType]
  result: <model>Type
}

type <model>UpdatePayload {
  ok: Boolean
  errors: [errorType]
  result: <model>Type
}

type <model>DeletePayload {
  ok: Boolean
  errors: [errorType]
}

input <model>WhereInput {
  ...<fields Mapping>
}

input <model>CreateInput {
  ...<fields Mapping>
}

input <model>UpdateInput {
  ...<fields Mapping>
}

input <model>OrderByInput {
  ...<fields Mapping>
}

input <model>CreateNestedInput {
  create: <related_model>CreateInput
  connect: <related_model>WhereInput
}

input <model>CreateNestedManyInput {
  create: [<related_model>CreateInput]
  connect: [<related_model>WhereInput]
}

input <model>UpdateNestedInput {
  create: <related_model>CreateInput
  update: <related_model>UpdateInput
  connect: <related_model>WhereInput
  delete: Boolean
  disconnect: Boolean
}

input <model>UpdateNestedManyInput {
  create: [<related_model>CreateInput]
  update: [<related_model>UpdateWithWhereInput]
  connect: [<related_model>WhereInput]
  delete: [<related_model>WhereInput]
  disconnect: [<related_model>WhereInput]
}

input <model>UpdateWithWhereInput {
  where: <model>WhereInput
  input: <model>UpdateInput
}Filetype File {
  url: String
  size: Int
  filename: String
  content: Binary
}Represents File, it's converted for models.FileField and models.ImageField. The
content field is deactivated by default, set theFILE_TYPE_CONTENT_FIELD_ACTIVEsetting toTruefor activate.FileInputinput FileInput {
  upload: Upload
  filename: String
  content: Binary
}Input type used to upload the file by giving a name and the content of the file.
The upload field appears if graphene-file-upload is installed, it is used to
upload this theMultipart Request Spec.Binaryscalar BinaryRepresentsBytesthat are base64 encoded and decoded.OrderEnumenum OrderEnum {
  ASC
  DESC
}

enum OrderStringEnum {
  ASC
  DESC
  IASC
  IDESC
}Scalar filtersinput IDFilter {
  equals: ID
  exact: ID
  in: [ID]
  isnull: Boolean
}

input BooleanFilter {
  equals: Boolean
  exact: Boolean
  in: [Boolean]
  isnull: Boolean
}

input UUIDFilter {
  equals: UUID
  exact: UUID
  in: [UUID]
  isnull: Boolean
}

input StringFilter {
  equals: String
  exact: String
  in: [String]
  isnull: Boolean
  contains: String
  startswith: String
  endswith: String
  regex: String
  iexact: String
  icontains: String
  istartswith: String
  iendswith: String
}

input IntFilter {
  equals: Int
  exact: Int
  in: [Int]
  isnull: Boolean
  gt: Int
  gte: Int
  lt: Int
  lte: Int
  contains: Int
  startswith: Int
  endswith: Int
  regex: String
}

input FloatFilter {
  equals: Float
  exact: Float
  in: [Float]
  isnull: Boolean
  gt: Float
  gte: Float
  lt: Float
  lte: Float
  contains: Float
  startswith: Float
  endswith: Float
  regex: String
}

input TimeFilter {
  equals: Time
  exact: Time
  in: [Time]
  isnull: Boolean
  gt: Time
  gte: Time
  lt: Time
  lte: Time
  hour: IntFilter
  minute: IntFilter
  second: IntFilter
}

input DateFilter {
  equals: Date
  exact: Date
  in: [Date]
  isnull: Boolean
  gt: Date
  gte: Date
  lt: Date
  lte: Date
  year: IntFilter
  month: IntFilter
  day: IntFilter
  weekDay: IntFilter
}

input DatetimeFilter {
  equals: DateTime
  exact: DateTime
  in: [DateTime]
  isnull: Boolean
  gt: DateTime
  gte: DateTime
  lt: DateTime
  lte: DateTime
  year: IntFilter
  month: IntFilter
  day: IntFilter
  weekDay: IntFilter
  hour: IntFilter
  minute: IntFilter
  second: IntFilter
}