Metadata-Version: 2.4
Name: drf-partial-response-fields
Version: 1.0.6
Summary: GraphQL-like sparse fieldsets and automatic query optimization for Django REST Framework
Project-URL: Homepage, https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/
Project-URL: Documentation, https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/getting-started/
Project-URL: Repository, https://github.com/MahmoudGShake/MahmoudPackages/tree/master/drf-partial-response-fields
Project-URL: Issues, https://github.com/MahmoudGShake/MahmoudPackages/issues
Project-URL: Changelog, https://github.com/MahmoudGShake/MahmoudPackages/blob/master/drf-partial-response-fields/CHANGELOG.md
Author-email: Mahmoud Gamal <mahmoudgshaker2018@gmail.com>
Maintainer-email: Mahmoud Gamal <mahmoudgshaker2018@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,django,djangorestframework,drf,fields,graphql,n+1,query-optimization,rest,sparse-fieldsets
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: django<5.3,>=4.2
Requires-Dist: djangorestframework>=3.14
Provides-Extra: dev
Requires-Dist: black>=24.10.0; extra == 'dev'
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: django-stubs[compatible-mypy]>=5.1.0; extra == 'dev'
Requires-Dist: djangorestframework-stubs[compatible-mypy]>=3.15.0; extra == 'dev'
Requires-Dist: drf-spectacular>=0.27; extra == 'dev'
Requires-Dist: factory-boy>=3.3.0; extra == 'dev'
Requires-Dist: hypothesis>=6.112.0; extra == 'dev'
Requires-Dist: mkdocs-material>=9.5.0; extra == 'dev'
Requires-Dist: mkdocs>=1.6.0; extra == 'dev'
Requires-Dist: mkdocstrings[python]>=0.26.0; extra == 'dev'
Requires-Dist: mypy>=1.13.0; extra == 'dev'
Requires-Dist: pre-commit>=3.8.0; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest-django>=4.9.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.6.0; extra == 'dev'
Requires-Dist: pytest>=8.3.0; extra == 'dev'
Requires-Dist: ruff>=0.6.9; extra == 'dev'
Requires-Dist: tox-gh-actions>=3.2.0; extra == 'dev'
Requires-Dist: tox>=4.21.0; extra == 'dev'
Requires-Dist: twine>=5.1.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.26.0; extra == 'docs'
Provides-Extra: openapi
Requires-Dist: drf-spectacular>=0.27; extra == 'openapi'
Provides-Extra: test
Requires-Dist: drf-spectacular>=0.27; extra == 'test'
Requires-Dist: factory-boy>=3.3.0; extra == 'test'
Requires-Dist: hypothesis>=6.112.0; extra == 'test'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
Requires-Dist: pytest-django>=4.9.0; extra == 'test'
Requires-Dist: pytest-xdist>=3.6.0; extra == 'test'
Requires-Dist: pytest>=8.3.0; extra == 'test'
Description-Content-Type: text/markdown

# drf-partial-response-fields

[![PyPI version](https://img.shields.io/pypi/v/drf-partial-response-fields.svg)](https://pypi.org/project/drf-partial-response-fields/)
[![Python versions](https://img.shields.io/pypi/pyversions/drf-partial-response-fields.svg)](https://pypi.org/project/drf-partial-response-fields/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

GraphQL-like sparse fieldsets for Django REST Framework — with automatic
`select_related` / `prefetch_related` / `only()` query optimization, so
requesting fewer fields also means fewer queries and less data transferred.

```
GET /api/articles/1/?fields=title,author(name,email),tags(label)
```

```json
{
  "title": "Shipping Faster with Sparse Fieldsets",
  "author": { "name": "Ada Lovelace", "email": "ada@example.com" },
  "tags": [{ "label": "performance" }, { "label": "django" }]
}
```

## Why

Fetching the full representation of a resource is wasteful when a client
only needs a few fields — especially on mobile, in list views, or in
BFF-style aggregation layers. Most "sparse fieldset" implementations for
DRF only filter the *serializer output* and leave the ORM query untouched,
so you save bytes on the wire but still pay for every join and every
`SerializerMethodField` query. This package does both: it filters what gets
serialized **and** rewrites the queryset so the database only does the work
that's actually needed.

## Features

- **Nested field selection**: `?fields=title,author(name,email)`
- **Deep nesting**: any depth, e.g. `author(company(name,address(city)))`
- **Exclusion**: `?fields=-internal_notes,-legacy_id`
- **Aliasing**: `?fields=publishedAt:created_at`
- **Wildcards**: `?fields=*` (explicit "no restriction")
- **Works with**: `ModelSerializer`, nested serializers, `SerializerMethodField`,
  pagination, `ViewSet`/`GenericAPIView`/`APIView`, the Browsable API, and
  OpenAPI schema generation (via `drf-spectacular`)
- **Automatic query optimization**: `select_related`, `prefetch_related`
  (including recursively-optimized nested `Prefetch` querysets), and
  `only()` are derived from the requested fields — see
  [`docs/performance.md`](docs/performance.md) for measured query-count
  reductions.
- **Safe by default**: unrequested `SerializerMethodField`s are never
  invoked, so expensive computed fields only cost what they cost when a
  client actually asks for them.
- **Fully typed**, PEP 561 compatible, `mypy --strict` clean.

## Installation

```bash
pip install drf-partial-response-fields

# with OpenAPI schema support
pip install drf-partial-response-fields[openapi]
```

Requires Python 3.10+, Django 4.2+, and Django REST Framework 3.14+.

## Quick Start

```python
# serializers.py
from rest_framework import serializers
from drf_partial_response_fields import PartialFieldsModelSerializer


class AuthorSerializer(PartialFieldsModelSerializer):
    class Meta:
        model = Author
        fields = ["id", "name", "email"]


class ArticleSerializer(PartialFieldsModelSerializer):
    author = AuthorSerializer()

    class Meta:
        model = Article
        fields = ["id", "title", "body", "author"]
```

```python
# views.py
from rest_framework import viewsets
from drf_partial_response_fields import PartialResponseMixin


class ArticleViewSet(PartialResponseMixin, viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
```

That's it — `GET /articles/?fields=title,author(name)` now returns only
`title` and `author.name`, and the underlying queryset automatically gets
`select_related("author").only("id", "title", "author__id", "author__name")`.

See [`docs/quickstart.md`](docs/quickstart.md) and
[`docs/advanced-usage.md`](docs/advanced-usage.md) for aliasing, exclusion,
`SerializerMethodField` optimization hints, and plain-`APIView` integration.

## Documentation

Full documentation is available at
[Documentation Home Page](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/), including:

- [Getting Started](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/getting-started)
- [Installation](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/installation)
- [Configuration](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/configuration) / [Settings](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/settings)
- [Quick Start](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/quickstart)
- [Advanced Usage](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/advanced-usage)
- [Architecture](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/architecture)
- [API Reference](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/api-reference)
- [Examples](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/examples)
- [Common Patterns](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/common-patterns)
- [Performance](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/performance)
- [Security](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/security)
- [Testing](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/testing)
- [Deployment](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/deployment)
- [FAQ](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/faq)
- [Troubleshooting](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/troubleshooting)

## Contributing

Contributions are welcome — see [Contributing](https://mahmoudgshake.github.io/MahmoudPackages/drf-partial-response-fields/contributing).

## License

MIT — see [LICENSE](https://github.com/MahmoudGShake/MahmoudPackages/blob/master/drf-partial-response-fields/LICENSE).
