drf-nested-forms


Namedrf-nested-forms JSON
Version 1.1.8 PyPI version JSON
download
home_pagehttp://github.com/emperorDuke/nested_formdata
SummaryA library that parses nested json or form data to python object
upload_time2023-10-25 18:56:33
maintainer
docs_urlNone
authorDuke Effiom
requires_python
licenseMIT
keywords drf nested form html_formsdrf_nested_forms restframework nested json
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage No coveralls.
            # DRF NESTED FORMS

A library that parses nested json or form data to python object.

[![Build Status](https://travis-ci.com/emperorDuke/nested_formdata.svg?branch=master)](https://travis-ci.com/emperorDuke/nested_formdata)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/emperorDuke/nested_formdata)](https://github.com/emperorDuke/nested_formdata/releases)
[![PyPI - License](https://img.shields.io/pypi/l/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)
[![PyPI - Django Version](https://img.shields.io/pypi/djversions/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)
[![PyPI](https://img.shields.io/pypi/v/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)


# Overview

SPA's, sometimes send nested form data or json as requests encoded by some javascript libraries like [json-form-data](https://github.com/hyperatom/json-form-data#readme) which can be difficult to handle due to the key naming conventions. This library helps to eliminate that difficulty, by parsing that nested requests into a more predictable python object that can be used by libraries like [drf_writable_nested](https://github.com/beda-software/drf-writable-nested#readme) or used directly in the code.

# Installation

It is available via pypi:

```
pip install drf_nested_forms
```

# Usage

The utiliy class can be used directly in any part of the code.

```python

from drf_nested_forms.utils import NestedForm

data = {
    'item[attribute][0][user_type]': 'size',
    'item[attribute][1][user_type]': '',
    'item[verbose][]': '',
    'item[variant][vendor_metric]': '[]',
    'item[variant][metric_verbose_name]': 'Large',
    'item[foo][baaz]': 'null',
}

options = {
    'allow_blank': True,
    'allow_empty': False
}
```

## Note

`.is_nested()` should be called before accessing the `.data`

```python
form = NestedForm(data, **options)
form.is_nested(raise_exception=True)
```

The parsed result will look like below:

```python
print(form.data)

data = {
    'item': {
        'attribute': [
            {'user_type': 'size'},
            {'user_type': ''}
        ],
        'verbose': [''],
        'variant': {
            'vendor_metric': None,
            'metric_verbose_name': 'Large'
        },
        'foo': { 'baaz': None }
    }
}
```

# DRF Integration

The parser is used with a djangorestframework view classes.

## Parser classes supported:

- `NestedMultiPartParser`: is a default DRF multipart parser that suppport parsing nested form data.
- `NestedJSONParser`: is a default DRF JSONParser that support parsing nested json request.

Add the parser to your django settings file

```python

#...

REST_FRAMEWORK = {
    DEFAULT_PARSER_CLASSES = [
        # nested parser are just default DRF parsers with extended
        # functionalities to support nested

        'drf_nested_forms.parsers.NestedMultiPartParser',
        'drf_nested_forms.parsers.NestedJSONPartParser',
        'rest_framework.parsers.FormParser',

        # so this settings will work in respective of a nested request
        # or not
    ]
}

#...

```

To change default settings of the parsers, add `OPTIONS` to `NESTED_FORM_PARSER` with the new settings to your django settings file

```python
#..

NESTED_FORM_PARSER = {
    'OPTIONS': {
        'allow_empty': False,
        'allow_blank': True
    }
}

#...

```

The parsers can also be used directly in a `rest_framework` view class

```python

from rest_framework.views import APIView
from rest_framework.parsers import FormParser
from rest_framework.response import Response

from drf_nested_forms.parsers import NestedMultiPartParser, NestedJSONParser

class TestMultiPartParserView(APIView):
    parser_classes = (NestedMultiPartParser, FormParser)

    def post(self, request):
        return Response(data=request.data, status=200)

# or

class TestJSONParserView(APIView):
    parser_classes = (NestedJSONParser, FormParser)

    def post(self, request):
        return Response(data=request.data, status=200)

```

For example, a form or JSON data with nested params like below can be posted to any of the above drf view:

```python
data = {
    '[0][attribute]': 'true',
    '[0][verbose][0]': 'bazz',
    '[0][verbose][1]': 'foo',
    '[0][variant][vendor_metric]': 'null',
    '[0][variant][metric_verbose_name]': 'Large',
    '[0][foo][baaz]': 'false',
    '[1][attribute]': 'size',
    '[1][verbose]': '[]',
    '[1][variant][vendor_metric]': '{}',
    '[1][variant][metric_verbose_name][foo][baaz][]': 'Large',
    '[1][foo][baaz]': '',
    '[1][logo]': '235'
}
```

after being parsed, the `request.data` will look like this:

```python
print(request.data)

data = [
    {
        'attribute': True,
        'verbose': ['bazz', 'foo'],
        'variant': {
            'vendor_metric': None,
            'metric_verbose_name': 'Large'
        },
        'foo': { 'baaz': False }
    },
    {
        'attribute': 'size',
        'verbose': None,
        'variant': {
            'vendor_metric': None,
            'metric_verbose_name': { 'foo': { 'baaz': ['Large'] } }
        },
        'foo': { 'baaz': '' },
        'logo': 235
    }
]
```

# Options

| Option      | Default | Description                           |
| ----------- | ------- | ------------------------------------- |
| allow_blank | `True`  | shows empty string `''` in the object |
| allow_empty | `False` | shows empty `list` or `dict` object   |

# Running Tests

To run the current test suite, execute the following from the root of the project:

```
python runtests.py
```

# Author

@Copyright 2021, Duke Effiom

            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/emperorDuke/nested_formdata",
    "name": "drf-nested-forms",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "drf,nested form,html_formsdrf_nested_forms,restframework,nested json",
    "author": "Duke Effiom",
    "author_email": "effiomduke@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/c6/ae/ef5de4614e0f1ec8941890990cec54e580665a4382b43a2da77a1d0ab535/drf_nested_forms-1.1.8.tar.gz",
    "platform": null,
    "description": "# DRF NESTED FORMS\r\n\r\nA library that parses nested json or form data to python object.\r\n\r\n[![Build Status](https://travis-ci.com/emperorDuke/nested_formdata.svg?branch=master)](https://travis-ci.com/emperorDuke/nested_formdata)\r\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/emperorDuke/nested_formdata)](https://github.com/emperorDuke/nested_formdata/releases)\r\n[![PyPI - License](https://img.shields.io/pypi/l/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)\r\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)\r\n[![PyPI - Django Version](https://img.shields.io/pypi/djversions/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)\r\n[![PyPI](https://img.shields.io/pypi/v/drf_nested_forms)](https://pypi.python.org/pypi/drf-nested-forms)\r\n\r\n\r\n# Overview\r\n\r\nSPA's, sometimes send nested form data or json as requests encoded by some javascript libraries like [json-form-data](https://github.com/hyperatom/json-form-data#readme) which can be difficult to handle due to the key naming conventions. This library helps to eliminate that difficulty, by parsing that nested requests into a more predictable python object that can be used by libraries like [drf_writable_nested](https://github.com/beda-software/drf-writable-nested#readme) or used directly in the code.\r\n\r\n# Installation\r\n\r\nIt is available via pypi:\r\n\r\n```\r\npip install drf_nested_forms\r\n```\r\n\r\n# Usage\r\n\r\nThe utiliy class can be used directly in any part of the code.\r\n\r\n```python\r\n\r\nfrom drf_nested_forms.utils import NestedForm\r\n\r\ndata = {\r\n    'item[attribute][0][user_type]': 'size',\r\n    'item[attribute][1][user_type]': '',\r\n    'item[verbose][]': '',\r\n    'item[variant][vendor_metric]': '[]',\r\n    'item[variant][metric_verbose_name]': 'Large',\r\n    'item[foo][baaz]': 'null',\r\n}\r\n\r\noptions = {\r\n    'allow_blank': True,\r\n    'allow_empty': False\r\n}\r\n```\r\n\r\n## Note\r\n\r\n`.is_nested()` should be called before accessing the `.data`\r\n\r\n```python\r\nform = NestedForm(data, **options)\r\nform.is_nested(raise_exception=True)\r\n```\r\n\r\nThe parsed result will look like below:\r\n\r\n```python\r\nprint(form.data)\r\n\r\ndata = {\r\n    'item': {\r\n        'attribute': [\r\n            {'user_type': 'size'},\r\n            {'user_type': ''}\r\n        ],\r\n        'verbose': [''],\r\n        'variant': {\r\n            'vendor_metric': None,\r\n            'metric_verbose_name': 'Large'\r\n        },\r\n        'foo': { 'baaz': None }\r\n    }\r\n}\r\n```\r\n\r\n# DRF Integration\r\n\r\nThe parser is used with a djangorestframework view classes.\r\n\r\n## Parser classes supported:\r\n\r\n- `NestedMultiPartParser`: is a default DRF multipart parser that suppport parsing nested form data.\r\n- `NestedJSONParser`: is a default DRF JSONParser that support parsing nested json request.\r\n\r\nAdd the parser to your django settings file\r\n\r\n```python\r\n\r\n#...\r\n\r\nREST_FRAMEWORK = {\r\n    DEFAULT_PARSER_CLASSES = [\r\n        # nested parser are just default DRF parsers with extended\r\n        # functionalities to support nested\r\n\r\n        'drf_nested_forms.parsers.NestedMultiPartParser',\r\n        'drf_nested_forms.parsers.NestedJSONPartParser',\r\n        'rest_framework.parsers.FormParser',\r\n\r\n        # so this settings will work in respective of a nested request\r\n        # or not\r\n    ]\r\n}\r\n\r\n#...\r\n\r\n```\r\n\r\nTo change default settings of the parsers, add `OPTIONS` to `NESTED_FORM_PARSER` with the new settings to your django settings file\r\n\r\n```python\r\n#..\r\n\r\nNESTED_FORM_PARSER = {\r\n    'OPTIONS': {\r\n        'allow_empty': False,\r\n        'allow_blank': True\r\n    }\r\n}\r\n\r\n#...\r\n\r\n```\r\n\r\nThe parsers can also be used directly in a `rest_framework` view class\r\n\r\n```python\r\n\r\nfrom rest_framework.views import APIView\r\nfrom rest_framework.parsers import FormParser\r\nfrom rest_framework.response import Response\r\n\r\nfrom drf_nested_forms.parsers import NestedMultiPartParser, NestedJSONParser\r\n\r\nclass TestMultiPartParserView(APIView):\r\n    parser_classes = (NestedMultiPartParser, FormParser)\r\n\r\n    def post(self, request):\r\n        return Response(data=request.data, status=200)\r\n\r\n# or\r\n\r\nclass TestJSONParserView(APIView):\r\n    parser_classes = (NestedJSONParser, FormParser)\r\n\r\n    def post(self, request):\r\n        return Response(data=request.data, status=200)\r\n\r\n```\r\n\r\nFor example, a form or JSON data with nested params like below can be posted to any of the above drf view:\r\n\r\n```python\r\ndata = {\r\n    '[0][attribute]': 'true',\r\n    '[0][verbose][0]': 'bazz',\r\n    '[0][verbose][1]': 'foo',\r\n    '[0][variant][vendor_metric]': 'null',\r\n    '[0][variant][metric_verbose_name]': 'Large',\r\n    '[0][foo][baaz]': 'false',\r\n    '[1][attribute]': 'size',\r\n    '[1][verbose]': '[]',\r\n    '[1][variant][vendor_metric]': '{}',\r\n    '[1][variant][metric_verbose_name][foo][baaz][]': 'Large',\r\n    '[1][foo][baaz]': '',\r\n    '[1][logo]': '235'\r\n}\r\n```\r\n\r\nafter being parsed, the `request.data` will look like this:\r\n\r\n```python\r\nprint(request.data)\r\n\r\ndata = [\r\n    {\r\n        'attribute': True,\r\n        'verbose': ['bazz', 'foo'],\r\n        'variant': {\r\n            'vendor_metric': None,\r\n            'metric_verbose_name': 'Large'\r\n        },\r\n        'foo': { 'baaz': False }\r\n    },\r\n    {\r\n        'attribute': 'size',\r\n        'verbose': None,\r\n        'variant': {\r\n            'vendor_metric': None,\r\n            'metric_verbose_name': { 'foo': { 'baaz': ['Large'] } }\r\n        },\r\n        'foo': { 'baaz': '' },\r\n        'logo': 235\r\n    }\r\n]\r\n```\r\n\r\n# Options\r\n\r\n| Option      | Default | Description                           |\r\n| ----------- | ------- | ------------------------------------- |\r\n| allow_blank | `True`  | shows empty string `''` in the object |\r\n| allow_empty | `False` | shows empty `list` or `dict` object   |\r\n\r\n# Running Tests\r\n\r\nTo run the current test suite, execute the following from the root of the project:\r\n\r\n```\r\npython runtests.py\r\n```\r\n\r\n# Author\r\n\r\n@Copyright 2021, Duke Effiom\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A library that parses nested json or form data to python object",
    "version": "1.1.8",
    "project_urls": {
        "Download": "http://github.com/emperorDuke/nested_formdata/archive/v1.1.8.tar.gz",
        "Homepage": "http://github.com/emperorDuke/nested_formdata"
    },
    "split_keywords": [
        "drf",
        "nested form",
        "html_formsdrf_nested_forms",
        "restframework",
        "nested json"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fc7e339ba9cf19f02202538ad51619855b48ab9d0e6d066c89641cad976e71b1",
                "md5": "a8fdc585dad9e3747c5321d2a34dd610",
                "sha256": "087fe5b6df32c95fcc605962a61109df08e7059580ef3adc6ba9de68d375b57b"
            },
            "downloads": -1,
            "filename": "drf_nested_forms-1.1.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a8fdc585dad9e3747c5321d2a34dd610",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 10079,
            "upload_time": "2023-10-25T18:56:25",
            "upload_time_iso_8601": "2023-10-25T18:56:25.392532Z",
            "url": "https://files.pythonhosted.org/packages/fc/7e/339ba9cf19f02202538ad51619855b48ab9d0e6d066c89641cad976e71b1/drf_nested_forms-1.1.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c6aeef5de4614e0f1ec8941890990cec54e580665a4382b43a2da77a1d0ab535",
                "md5": "5c7c55c2ec7682c5083e344698c4dc11",
                "sha256": "5d086b7e68c56915f430bd5a1beffe0c79a6ac48424732287d056c5322e65f93"
            },
            "downloads": -1,
            "filename": "drf_nested_forms-1.1.8.tar.gz",
            "has_sig": false,
            "md5_digest": "5c7c55c2ec7682c5083e344698c4dc11",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 12928,
            "upload_time": "2023-10-25T18:56:33",
            "upload_time_iso_8601": "2023-10-25T18:56:33.053957Z",
            "url": "https://files.pythonhosted.org/packages/c6/ae/ef5de4614e0f1ec8941890990cec54e580665a4382b43a2da77a1d0ab535/drf_nested_forms-1.1.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-25 18:56:33",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "emperorDuke",
    "github_project": "nested_formdata",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "drf-nested-forms"
}
        
Elapsed time: 0.17775s