django-relay-endpoint


Namedjango-relay-endpoint JSON
Version 2.0.0 PyPI version JSON
download
home_pagehttps://github.com/Elawphant/django_relay_endpoint
SummaryDjango addon to automatically configure graphql endpoints based on Django models.
upload_time2024-05-19 06:59:56
maintainerNone
docs_urlNone
authorGevorg Hakobyan
requires_python>=3.8
licenseMIT
keywords
VCS
bugtrack_url
requirements graphene-django graphene-file-upload django_filter jsonschema
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django Relay Endpoint

"Django Relay Endpoint" is a Django addon that automatically configures a customizable graphql endpoint from models.
The addon is made for "graphene_django".

This addon contains modules for dynamic autogeneration of an endpoint.
However, given the limitations of customization, instead, `dre-from-model` and `dre-from-json` commands were supplied in version 2. These commands use the `django_relay_endpoint`'s `DjangoClientIDMutation`, validators and persissions for ease of customization. They can be imported directly from `django_relay_endpoint` package.

## Table of Contents

- [Django Relay Endpoint](#django-relay-endpoint)
  - [Table of Contents](#table-of-contents)
  - [Requirements](#requirements)
  - [Installation](#installation)
  - [How to use](#how-to-use)
  - [Commands](#commands)
    - [Usage dre-from-model](#usage-dre-from-model)
    - [Usage dre-from-json](#usage-dre-from-json)
  - [Dynamic endpoint](#dynamic-endpoint)
    - [Simple usage](#simple-usage)
    - [Adding custom query and mutation types](#adding-custom-query-and-mutation-types)
    - [Configuring custom NodeType for node root field](#configuring-custom-nodetype-for-node-root-field)
    - [Configuring NodeType subclasses](#configuring-nodetype-subclasses)
  - [Validators](#validators)
  - [Permissions](#permissions)
  - [Useful subclasses and tools](#useful-subclasses-and-tools)
  - [License](#license)
  - [Documentation](#documentation)
  - [Tip the author](#tip-the-author)

## Requirements

Python 3.8 or higher
Django 4.2.7 or higher

It is possible that the addon will work with lower code setup. Keep in mind that the code uses `__init_subclass__` method and format string. It was tested made with the following code setup

- Python 3.11.2 (probably will work on older versions, the addon was tested on 3.11 and 3.12)
- Django >= 4.2.7
- graphene-django >= 3.3.0
- graphene-file-upload >= 1.3.0
- django_filter >= 23.3.0

This package will also install `graphene-django`, `graphene-file-upload` and `django_filter`.

## Installation

Install using pip:

```zsh
pip install django-relay-endpoint
```

Install using uv

```zsh

uv pip install django-relay-endpoint
```

## How to use

1. Add `'graphene_django'` to your project's `settings.py`:

```py
INSTALLED_APPS = [
    # ... other apps and addons
    'graphene_django',
]
```

Done, now you can use the commands to generate the necessary modules.

## Commands

The addon comes with two commands

- dre-from-model
- dre-from-json

The `dre-from-model` one generates modules from a single model, while `dre-from-json` generates a type schema from a json file. `dre` stands for `django-relay-endpoint`.

The commands will generate `nodes`, `input_types`, `queries` and `mutations` folders inside the provided app, generate necessary modules inside them with conventional naming, as well as create a `urls` and `schema` modules. 

**Imporatant!** After the generation of the schema, you must import and extend the respective query, mutation and subscription classes inside the `schema` module as well as inlcude the `urls` module in your project's `urls` module.

### Usage dre-from-model

Example usage

```zsh
python manage.py dre-from-model app_label.ModelName --in--app api
```

Available arguments/options:

- "model": dot-separated app_label and model class name, e.g. 'app.Model'
- "--in-app", "-in": the django app where to generate the schema models in
- "--overwrite", "-owt": whether to overwrite the modeles o not, defaults to False
- "--query", "-q": whether to generate query modules or not, defaults to True
- "--query-fields", "-qf": a list of of fields to configure, if none provided, all model fields will be configured
- "--create-mutation", "-cm": whether to generate mutation modules for creation, defaults to `True`
- "--create-mutation-fields", "-cmf": the list of fields to configure, if none provided, all model fields will be configured
- "--update-mutation", "-um": whether to generate mutation modules for updating, defaults to `True`
- "--update-mutation-fields", "-umf": the list of fields to configure, if none provided, all model fields will be configured
- "--delete-mutation", "-dm": whether to generate mutation modules for deletion, defaults to `True`

### Usage dre-from-json

Example usage

```zsh
python manage.py dre-from-schema --read app_label/type_config.json
```

Available arguments/options:

- "--read", "-r: path to the json file.

The json file must have the following structure.

- `schema_app` (str): required, the `app_label`, where the schema modules will be generated
- `type_config` (list[dict]): required, each dictionary is for each model, and accepts the following kwargs:
- `overwrite` (bool): optional, whether to overwrite existing files or not

  - `model` (string): required, must be declared in form of `app_label.ModelName`.
  - `overwrite` (bool): (optional) same as top level `overwrite`, except if it is present, the top level overwrite will not apply.
  - `query` (bool): (optional) whether to generate query modules or not, defaults to `True`
  - `query_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured
  - `create_mutation` (bool): whether to generate mutation modules for creation, defaults to `True`
  - `create_mutation_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured
  - `update_mutation` whether to generate mutation modules for updating, defaults to `True`
  - `update_mutation_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured
  - `delete_mutation` (bool): whether to generate mutation modules for deletion, defaults to `True`

**Overwrite** will not overwrite existing `urls` and `schema` modules.

**Django relay endpoint comes with autoconfigurable dynamic endpoint, which has limitations. Instead better use the commands for better manual customization.** The autoconfiguration modules are deprecated and the author does not intend to support dynamic endpoint furthermore.

## Dynamic endpoint

### Simple usage

Declare your NodeTypes and pass it to the SchemaConfigurator to get the schema. e.g.

```py
# endpoint.py
from django_relay_endpoint import NodeType, SchemaConfigurator

class AuthorType(NodeType):
    @staticmethod
    def get_queryset(object_type, queryset, info):
        return queryset.filter(age__gte=35) # filter authors with age higher than 35

    class Meta:
        model = 'my_app.Author'
        fields = ['id', 'name', 'age', 'books']
        filter_fields = {
            'id': ('exact',),
            'name': ('iexact', 'icontains'),
        }
        extra_kwargs: {
            'name': {
                "required": True,
            },
            'age': {
                "required": True,
            }
        }

class BookType(NodeType):
    class Meta:
        model = 'my_app.Book'
        fields = ['id', 'name', 'authors']


schema = SchemaConfigurator([
    AuthorType,
    BookType,
]).schema()

```

In your `urls.py` add the endpoint

```py
# urls.py
from graphene_file_upload.django import FileUploadGraphQLView
from my_app.endpoint import schema
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
    # ... other urls
    path("graphql_dashboard_v1", csrf_exempt(FileUploadGraphQLView.as_view(graphiql=True, schema=schema))),
]

```

It uses `FileUploadGraphQLView` from `graphene_file_upload.django` to support file uploads.

### Adding custom query and mutation types

The `SchemaConfigurator` **instance** has `query` and `mutation` properties of type List, when instantiated.

Custom object types can be appended to the `query` and `mutation` properties: e.g.

```py
# let's imagine we have created a mutation that handles login
from my_app.models import Book

class AuthType(Mutation): ...

# and we have BookType configured with NodeType 
class BookType(NodeType):
    class Meta:
        model = Book
        fields = '__all__'

schema = SchemaConfigurator([
    BookType,
]) # will instantiate the SchemaConfigurator with rootfields form BookType.

schema.mutations.append(AuthType) # adds AuthType to mutations.

schema = schema.schema() # overwrite schema with actual schema. This will create the actual schema by extending all types and return the schema.

```

### Configuring custom NodeType for node root field

Per relay specification the endpoint must implement `node` root field.
The configured server implements the `node` root field with default configuration per graphene.

If the developer wants to provide custom `NodeType` it can do so by subclassing `graphene.ObjectType` and providing own resolver, e.g.

```py
class CustomNodeType(graphene.ObjectType):
    node = graphene.relay.Node.Field()

    @classmethod
    resolve_node(cls, root, info, id):
        # implement custom type identification using from_global_id
        ...

schema = SchemaConfigurator([
    AuthorType,
    BookType,
])

# overwrite the default NodeType with CustomNodeType
schema.node_type = CustomNodeType

# Overwrite schema with actual generated schema.
schema = schema.schema()

```

### Configuring NodeType subclasses

A subclass of NodeType can be configured via its Meta class.

Available options are as follows:

**Following options can be configured on class Meta**:

- **model**: (Union[str, Type[models.Model]]) - a string composed of 'app_name.model_name' or actual django model.
- **fields**: List[str] | Literal["__all__"] - an explicit list of field names or '__all__'.
- **query_root_name**: str | None - a root field name. Defaults to lowered snake-case model._meta.verbose_name.
- **query_root_name_plural**: str | None - a root field name. Defaults to lowered snake-case model._meta.verbose_name_plural.
- **filter_fields**: Union[Dict[str, List[str]], List[str]] - fielter_fields configurations. see <https://docs.graphene-python.org/projects/django/en/latest/filtering/#filterable-fields>.
- **filterset_class**: FilterSet - a filterset_class. see <https://docs.graphene-python.org/projects/django/en/latest/filtering/#custom-filtersets>.
- **object_type_name**: str | None - The classname of the DjangoObjectType that will be configured. Defaults to camel-case `AppNameModelNameType`.
- **mutation_operations**: Literal["create", "update", "delete"] - similar to query_operations, this limits the root field configuration, defaults to `["create", "update", "delete"]`.
- **extra_kwargs**: Dict[str, Dict[str, Any]] - the mutation type fields are configured via assigned django form field; this option is similar to rest framework serializer `extra_kwargs`, which is a dictionary of field_names mapped to a dictionary of django form field kwargs. The configurator automatically maps the field to the respective form field: for field mapping see <https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/#field-types>. For relations, it maps the fields to `graphene.List(graphene.ID, **field_kwargs)` `and graphene.ID(**field_kwargs)`, it will also infer the `required` parameter value from the declared `allow_blank` and `allow_null` parameters of the respective model.field.
- **field_validators**: Dict[str, List[Callable]] - a dictionary of field_names mapped to the list of validators: see [Validators](#validators).
- **non_field_validators**: List[Callable] - list of validators: see [Validators](#validators).
- **success_keyword**: str - a success keyword for mutation responses. by defualt it is 'success'.
- **input_field_name**: str - a Input field name for mutations. Defaults to 'data'.
- **return_field_name**: str - the field name on the response on create and update mutations, if none provided, model._meta.model_name will be used.
- **permissions**: List[str] - A list of permission names, defaults to empty list, i.e. no permissions will be checked.
- **permission_classes**: List[Type[BasePermission]] - A list of permission classes. see [Permissions](#permissions).

**Following fields can be configured on the subclass of the NodeType**:

- **get_queryset**: Callable - a static get_queryset method. Important! this method should be declared as staticmethod, it will be returned with the configured subclass of DjangoObjectType, queryset and info. It behaves as overwrite of get_queryset method, but is a staticmethod. See the example in [How to use](#how-to-use).

## Validators

A validator passed to `field_validators` or `non_field_validators` is a function that takes the following arguments:

- **data**: the field value for field_validators and whole data object for non_field_validators
- **not_updated_model_instance**: the instance with the state before merging data with the instance
- **info**: the graphene resolve info object instance.

## Permissions

The addon has extended DjangoObjectType and ClientIDMutation to support string permissions and class based permissions for queryset and object level permission checks.

Class based permissions extend custom `BasePermission` class, which implements `has_permission(self, info) -> bool` and `has_object_permission(self, info, obj) -> bool` methods. If the class returns `False` a permission-denied error will be raised. Following default permission classes can be found in graphene_relay_endpoint:

- **AllowAny**: This class is intended only for explicit declaration. It does nothing similar to the same permission in REST framework
- **IsAuthenticated**: Checks for authentication.
- **IsAdminUser**: Checks for admin privilege.
- **IsAuthenticatedOrReadOnly**: Limits mutation operations to authenticated users.
- **BasePermission**: A base class to subclass for custom permission classes.

## Useful subclasses and tools

The addon comes with builtin DjangoClientIDMutation abstract subclass, which implements following methods

- **get_queryset**: same as on graphen_django.DjangoObjectType
- **get_node**: same as on graphen_django.DjangoObjectType
- **create_node**: creates an empty instance of the given mode
- **validate**: validates data via 'field_validators' and 'non_field_validators' supplied with the subclass of NodeType.
- **update_instance**: set's the values on the instance from data. For to-many relations it uses the `add_<field_name>` and `remove_<field_name>` convention. First it adds than it removes. The client can pass both, and the relations will be added and removed consecutively before being saved.

N.B. DjangoClientIDMutation does not implement a `mutate_and_get_payload` classmethod, the developer must implement it on a subclass.

## License

See the MIT licens in the LICENSE file in the project.

## Documentation

The addon is pretty simple. The [How to use](#how-to-use) and [Configuring NodeType subclasses](#configuring-nodetype-subclasses)  explains it all. Each piece of code is also documented with dockstrings and has respective type hints.
For additional information read the respective documentation:

- **graphene_django**: <https://docs.graphene-python.org/projects/django/>
- **graphene-file-upload**: <https://github.com/lmcgartland/graphene-file-upload>

## Tip the author

If this project has facilitated your job, saved time spent on boilerplate code and pain of standardizing and debugging a relay style endpoint, consider tipping (donating) the author with some crypto:

**Wallet**: `3N5ot3DA2vSLwEqhjTGhfVnGaAuQoWBrCf`

Thank you!

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Elawphant/django_relay_endpoint",
    "name": "django-relay-endpoint",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "Gevorg Hakobyan",
    "author_email": "gevorg.hakobyan@elawphant.am",
    "download_url": null,
    "platform": null,
    "description": "# Django Relay Endpoint\n\n\"Django Relay Endpoint\" is a Django addon that automatically configures a customizable graphql endpoint from models.\nThe addon is made for \"graphene_django\".\n\nThis addon contains modules for dynamic autogeneration of an endpoint.\nHowever, given the limitations of customization, instead, `dre-from-model` and `dre-from-json` commands were supplied in version 2. These commands use the `django_relay_endpoint`'s `DjangoClientIDMutation`, validators and persissions for ease of customization. They can be imported directly from `django_relay_endpoint` package.\n\n## Table of Contents\n\n- [Django Relay Endpoint](#django-relay-endpoint)\n  - [Table of Contents](#table-of-contents)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n  - [How to use](#how-to-use)\n  - [Commands](#commands)\n    - [Usage dre-from-model](#usage-dre-from-model)\n    - [Usage dre-from-json](#usage-dre-from-json)\n  - [Dynamic endpoint](#dynamic-endpoint)\n    - [Simple usage](#simple-usage)\n    - [Adding custom query and mutation types](#adding-custom-query-and-mutation-types)\n    - [Configuring custom NodeType for node root field](#configuring-custom-nodetype-for-node-root-field)\n    - [Configuring NodeType subclasses](#configuring-nodetype-subclasses)\n  - [Validators](#validators)\n  - [Permissions](#permissions)\n  - [Useful subclasses and tools](#useful-subclasses-and-tools)\n  - [License](#license)\n  - [Documentation](#documentation)\n  - [Tip the author](#tip-the-author)\n\n## Requirements\n\nPython 3.8 or higher\nDjango 4.2.7 or higher\n\nIt is possible that the addon will work with lower code setup. Keep in mind that the code uses `__init_subclass__` method and format string. It was tested made with the following code setup\n\n- Python 3.11.2 (probably will work on older versions, the addon was tested on 3.11 and 3.12)\n- Django >= 4.2.7\n- graphene-django >= 3.3.0\n- graphene-file-upload >= 1.3.0\n- django_filter >= 23.3.0\n\nThis package will also install `graphene-django`, `graphene-file-upload` and `django_filter`.\n\n## Installation\n\nInstall using pip:\n\n```zsh\npip install django-relay-endpoint\n```\n\nInstall using uv\n\n```zsh\n\nuv pip install django-relay-endpoint\n```\n\n## How to use\n\n1. Add `'graphene_django'` to your project's `settings.py`:\n\n```py\nINSTALLED_APPS = [\n    # ... other apps and addons\n    'graphene_django',\n]\n```\n\nDone, now you can use the commands to generate the necessary modules.\n\n## Commands\n\nThe addon comes with two commands\n\n- dre-from-model\n- dre-from-json\n\nThe `dre-from-model` one generates modules from a single model, while `dre-from-json` generates a type schema from a json file. `dre` stands for `django-relay-endpoint`.\n\nThe commands will generate `nodes`, `input_types`, `queries` and `mutations` folders inside the provided app, generate necessary modules inside them with conventional naming, as well as create a `urls` and `schema` modules. \n\n**Imporatant!** After the generation of the schema, you must import and extend the respective query, mutation and subscription classes inside the `schema` module as well as inlcude the `urls` module in your project's `urls` module.\n\n### Usage dre-from-model\n\nExample usage\n\n```zsh\npython manage.py dre-from-model app_label.ModelName --in--app api\n```\n\nAvailable arguments/options:\n\n- \"model\": dot-separated app_label and model class name, e.g. 'app.Model'\n- \"--in-app\", \"-in\": the django app where to generate the schema models in\n- \"--overwrite\", \"-owt\": whether to overwrite the modeles o not, defaults to False\n- \"--query\", \"-q\": whether to generate query modules or not, defaults to True\n- \"--query-fields\", \"-qf\": a list of of fields to configure, if none provided, all model fields will be configured\n- \"--create-mutation\", \"-cm\": whether to generate mutation modules for creation, defaults to `True`\n- \"--create-mutation-fields\", \"-cmf\": the list of fields to configure, if none provided, all model fields will be configured\n- \"--update-mutation\", \"-um\": whether to generate mutation modules for updating, defaults to `True`\n- \"--update-mutation-fields\", \"-umf\": the list of fields to configure, if none provided, all model fields will be configured\n- \"--delete-mutation\", \"-dm\": whether to generate mutation modules for deletion, defaults to `True`\n\n### Usage dre-from-json\n\nExample usage\n\n```zsh\npython manage.py dre-from-schema --read app_label/type_config.json\n```\n\nAvailable arguments/options:\n\n- \"--read\", \"-r: path to the json file.\n\nThe json file must have the following structure.\n\n- `schema_app` (str): required, the `app_label`, where the schema modules will be generated\n- `type_config` (list[dict]): required, each dictionary is for each model, and accepts the following kwargs:\n- `overwrite` (bool): optional, whether to overwrite existing files or not\n\n  - `model` (string): required, must be declared in form of `app_label.ModelName`.\n  - `overwrite` (bool): (optional) same as top level `overwrite`, except if it is present, the top level overwrite will not apply.\n  - `query` (bool): (optional) whether to generate query modules or not, defaults to `True`\n  - `query_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured\n  - `create_mutation` (bool): whether to generate mutation modules for creation, defaults to `True`\n  - `create_mutation_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured\n  - `update_mutation` whether to generate mutation modules for updating, defaults to `True`\n  - `update_mutation_fields` (list[str]): a list of of fields to configure, if none provided, all model fields will be configured\n  - `delete_mutation` (bool): whether to generate mutation modules for deletion, defaults to `True`\n\n**Overwrite** will not overwrite existing `urls` and `schema` modules.\n\n**Django relay endpoint comes with autoconfigurable dynamic endpoint, which has limitations. Instead better use the commands for better manual customization.** The autoconfiguration modules are deprecated and the author does not intend to support dynamic endpoint furthermore.\n\n## Dynamic endpoint\n\n### Simple usage\n\nDeclare your NodeTypes and pass it to the SchemaConfigurator to get the schema. e.g.\n\n```py\n# endpoint.py\nfrom django_relay_endpoint import NodeType, SchemaConfigurator\n\nclass AuthorType(NodeType):\n    @staticmethod\n    def get_queryset(object_type, queryset, info):\n        return queryset.filter(age__gte=35) # filter authors with age higher than 35\n\n    class Meta:\n        model = 'my_app.Author'\n        fields = ['id', 'name', 'age', 'books']\n        filter_fields = {\n            'id': ('exact',),\n            'name': ('iexact', 'icontains'),\n        }\n        extra_kwargs: {\n            'name': {\n                \"required\": True,\n            },\n            'age': {\n                \"required\": True,\n            }\n        }\n\nclass BookType(NodeType):\n    class Meta:\n        model = 'my_app.Book'\n        fields = ['id', 'name', 'authors']\n\n\nschema = SchemaConfigurator([\n    AuthorType,\n    BookType,\n]).schema()\n\n```\n\nIn your `urls.py` add the endpoint\n\n```py\n# urls.py\nfrom graphene_file_upload.django import FileUploadGraphQLView\nfrom my_app.endpoint import schema\nfrom django.views.decorators.csrf import csrf_exempt\n\nurlpatterns = [\n    # ... other urls\n    path(\"graphql_dashboard_v1\", csrf_exempt(FileUploadGraphQLView.as_view(graphiql=True, schema=schema))),\n]\n\n```\n\nIt uses `FileUploadGraphQLView` from `graphene_file_upload.django` to support file uploads.\n\n### Adding custom query and mutation types\n\nThe `SchemaConfigurator` **instance** has `query` and `mutation` properties of type List, when instantiated.\n\nCustom object types can be appended to the `query` and `mutation` properties: e.g.\n\n```py\n# let's imagine we have created a mutation that handles login\nfrom my_app.models import Book\n\nclass AuthType(Mutation): ...\n\n# and we have BookType configured with NodeType \nclass BookType(NodeType):\n    class Meta:\n        model = Book\n        fields = '__all__'\n\nschema = SchemaConfigurator([\n    BookType,\n]) # will instantiate the SchemaConfigurator with rootfields form BookType.\n\nschema.mutations.append(AuthType) # adds AuthType to mutations.\n\nschema = schema.schema() # overwrite schema with actual schema. This will create the actual schema by extending all types and return the schema.\n\n```\n\n### Configuring custom NodeType for node root field\n\nPer relay specification the endpoint must implement `node` root field.\nThe configured server implements the `node` root field with default configuration per graphene.\n\nIf the developer wants to provide custom `NodeType` it can do so by subclassing `graphene.ObjectType` and providing own resolver, e.g.\n\n```py\nclass CustomNodeType(graphene.ObjectType):\n    node = graphene.relay.Node.Field()\n\n    @classmethod\n    resolve_node(cls, root, info, id):\n        # implement custom type identification using from_global_id\n        ...\n\nschema = SchemaConfigurator([\n    AuthorType,\n    BookType,\n])\n\n# overwrite the default NodeType with CustomNodeType\nschema.node_type = CustomNodeType\n\n# Overwrite schema with actual generated schema.\nschema = schema.schema()\n\n```\n\n### Configuring NodeType subclasses\n\nA subclass of NodeType can be configured via its Meta class.\n\nAvailable options are as follows:\n\n**Following options can be configured on class Meta**:\n\n- **model**: (Union[str, Type[models.Model]]) - a string composed of 'app_name.model_name' or actual django model.\n- **fields**: List[str] | Literal[\"__all__\"] - an explicit list of field names or '__all__'.\n- **query_root_name**: str | None - a root field name. Defaults to lowered snake-case model._meta.verbose_name.\n- **query_root_name_plural**: str | None - a root field name. Defaults to lowered snake-case model._meta.verbose_name_plural.\n- **filter_fields**: Union[Dict[str, List[str]], List[str]] - fielter_fields configurations. see <https://docs.graphene-python.org/projects/django/en/latest/filtering/#filterable-fields>.\n- **filterset_class**: FilterSet - a filterset_class. see <https://docs.graphene-python.org/projects/django/en/latest/filtering/#custom-filtersets>.\n- **object_type_name**: str | None - The classname of the DjangoObjectType that will be configured. Defaults to camel-case `AppNameModelNameType`.\n- **mutation_operations**: Literal[\"create\", \"update\", \"delete\"] - similar to query_operations, this limits the root field configuration, defaults to `[\"create\", \"update\", \"delete\"]`.\n- **extra_kwargs**: Dict[str, Dict[str, Any]] - the mutation type fields are configured via assigned django form field; this option is similar to rest framework serializer `extra_kwargs`, which is a dictionary of field_names mapped to a dictionary of django form field kwargs. The configurator automatically maps the field to the respective form field: for field mapping see <https://docs.djangoproject.com/en/4.2/topics/forms/modelforms/#field-types>. For relations, it maps the fields to `graphene.List(graphene.ID, **field_kwargs)` `and graphene.ID(**field_kwargs)`, it will also infer the `required` parameter value from the declared `allow_blank` and `allow_null` parameters of the respective model.field.\n- **field_validators**: Dict[str, List[Callable]] - a dictionary of field_names mapped to the list of validators: see [Validators](#validators).\n- **non_field_validators**: List[Callable] - list of validators: see [Validators](#validators).\n- **success_keyword**: str - a success keyword for mutation responses. by defualt it is 'success'.\n- **input_field_name**: str - a Input field name for mutations. Defaults to 'data'.\n- **return_field_name**: str - the field name on the response on create and update mutations, if none provided, model._meta.model_name will be used.\n- **permissions**: List[str] - A list of permission names, defaults to empty list, i.e. no permissions will be checked.\n- **permission_classes**: List[Type[BasePermission]] - A list of permission classes. see [Permissions](#permissions).\n\n**Following fields can be configured on the subclass of the NodeType**:\n\n- **get_queryset**: Callable - a static get_queryset method. Important! this method should be declared as staticmethod, it will be returned with the configured subclass of DjangoObjectType, queryset and info. It behaves as overwrite of get_queryset method, but is a staticmethod. See the example in [How to use](#how-to-use).\n\n## Validators\n\nA validator passed to `field_validators` or `non_field_validators` is a function that takes the following arguments:\n\n- **data**: the field value for field_validators and whole data object for non_field_validators\n- **not_updated_model_instance**: the instance with the state before merging data with the instance\n- **info**: the graphene resolve info object instance.\n\n## Permissions\n\nThe addon has extended DjangoObjectType and ClientIDMutation to support string permissions and class based permissions for queryset and object level permission checks.\n\nClass based permissions extend custom `BasePermission` class, which implements `has_permission(self, info) -> bool` and `has_object_permission(self, info, obj) -> bool` methods. If the class returns `False` a permission-denied error will be raised. Following default permission classes can be found in graphene_relay_endpoint:\n\n- **AllowAny**: This class is intended only for explicit declaration. It does nothing similar to the same permission in REST framework\n- **IsAuthenticated**: Checks for authentication.\n- **IsAdminUser**: Checks for admin privilege.\n- **IsAuthenticatedOrReadOnly**: Limits mutation operations to authenticated users.\n- **BasePermission**: A base class to subclass for custom permission classes.\n\n## Useful subclasses and tools\n\nThe addon comes with builtin DjangoClientIDMutation abstract subclass, which implements following methods\n\n- **get_queryset**: same as on graphen_django.DjangoObjectType\n- **get_node**: same as on graphen_django.DjangoObjectType\n- **create_node**: creates an empty instance of the given mode\n- **validate**: validates data via 'field_validators' and 'non_field_validators' supplied with the subclass of NodeType.\n- **update_instance**: set's the values on the instance from data. For to-many relations it uses the `add_<field_name>` and `remove_<field_name>` convention. First it adds than it removes. The client can pass both, and the relations will be added and removed consecutively before being saved.\n\nN.B. DjangoClientIDMutation does not implement a `mutate_and_get_payload` classmethod, the developer must implement it on a subclass.\n\n## License\n\nSee the MIT licens in the LICENSE file in the project.\n\n## Documentation\n\nThe addon is pretty simple. The [How to use](#how-to-use) and [Configuring NodeType subclasses](#configuring-nodetype-subclasses)  explains it all. Each piece of code is also documented with dockstrings and has respective type hints.\nFor additional information read the respective documentation:\n\n- **graphene_django**: <https://docs.graphene-python.org/projects/django/>\n- **graphene-file-upload**: <https://github.com/lmcgartland/graphene-file-upload>\n\n## Tip the author\n\nIf this project has facilitated your job, saved time spent on boilerplate code and pain of standardizing and debugging a relay style endpoint, consider tipping (donating) the author with some crypto:\n\n**Wallet**: `3N5ot3DA2vSLwEqhjTGhfVnGaAuQoWBrCf`\n\nThank you!\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Django addon to automatically configure graphql endpoints based on Django models.",
    "version": "2.0.0",
    "project_urls": {
        "Homepage": "https://github.com/Elawphant/django_relay_endpoint"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bc28e03c7f1bf8fda84f4f7d90e0a389fa9419823019a4f42caa2d377866d23d",
                "md5": "abb831531ddcfe9dc7878f79c0ca2644",
                "sha256": "652b7a49dfdcfec6928dc9b537c5e8ca3d624f81d7d9a20febb3613e4d5e347c"
            },
            "downloads": -1,
            "filename": "django_relay_endpoint-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "abb831531ddcfe9dc7878f79c0ca2644",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 37854,
            "upload_time": "2024-05-19T06:59:56",
            "upload_time_iso_8601": "2024-05-19T06:59:56.764301Z",
            "url": "https://files.pythonhosted.org/packages/bc/28/e03c7f1bf8fda84f4f7d90e0a389fa9419823019a4f42caa2d377866d23d/django_relay_endpoint-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-19 06:59:56",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Elawphant",
    "github_project": "django_relay_endpoint",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "graphene-django",
            "specs": []
        },
        {
            "name": "graphene-file-upload",
            "specs": []
        },
        {
            "name": "django_filter",
            "specs": []
        },
        {
            "name": "jsonschema",
            "specs": []
        }
    ],
    "lcname": "django-relay-endpoint"
}
        
Elapsed time: 0.24327s