django-fastdrf 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. django_fastdrf-0.1.0/.gitignore +11 -0
  2. django_fastdrf-0.1.0/CHANGELOG.md +74 -0
  3. django_fastdrf-0.1.0/CODE_OF_CONDUCT.md +14 -0
  4. django_fastdrf-0.1.0/CONTRIBUTING.md +120 -0
  5. django_fastdrf-0.1.0/LICENSE +28 -0
  6. django_fastdrf-0.1.0/NOTICE +8 -0
  7. django_fastdrf-0.1.0/PKG-INFO +214 -0
  8. django_fastdrf-0.1.0/README.md +174 -0
  9. django_fastdrf-0.1.0/SECURITY.md +30 -0
  10. django_fastdrf-0.1.0/docs/README.md +15 -0
  11. django_fastdrf-0.1.0/docs/architecture.md +171 -0
  12. django_fastdrf-0.1.0/docs/commands.md +98 -0
  13. django_fastdrf-0.1.0/docs/configuration.md +158 -0
  14. django_fastdrf-0.1.0/docs/queries.md +166 -0
  15. django_fastdrf-0.1.0/docs/rendering.md +115 -0
  16. django_fastdrf-0.1.0/docs/schema-serializers.md +175 -0
  17. django_fastdrf-0.1.0/docs/serializers.md +251 -0
  18. django_fastdrf-0.1.0/docs/views.md +189 -0
  19. django_fastdrf-0.1.0/noxfile.py +110 -0
  20. django_fastdrf-0.1.0/pyproject.toml +72 -0
  21. django_fastdrf-0.1.0/release-notes.md +66 -0
  22. django_fastdrf-0.1.0/src/fastdrf/__init__.py +3 -0
  23. django_fastdrf-0.1.0/src/fastdrf/_classify.py +210 -0
  24. django_fastdrf-0.1.0/src/fastdrf/_compiled.py +131 -0
  25. django_fastdrf-0.1.0/src/fastdrf/_field_cache.py +158 -0
  26. django_fastdrf-0.1.0/src/fastdrf/_field_copy.py +244 -0
  27. django_fastdrf-0.1.0/src/fastdrf/_field_options.py +68 -0
  28. django_fastdrf-0.1.0/src/fastdrf/_inspection.py +25 -0
  29. django_fastdrf-0.1.0/src/fastdrf/_relations.py +206 -0
  30. django_fastdrf-0.1.0/src/fastdrf/apps.py +22 -0
  31. django_fastdrf-0.1.0/src/fastdrf/checks.py +108 -0
  32. django_fastdrf-0.1.0/src/fastdrf/codecs.py +97 -0
  33. django_fastdrf-0.1.0/src/fastdrf/compat.py +7 -0
  34. django_fastdrf-0.1.0/src/fastdrf/compiler.py +1681 -0
  35. django_fastdrf-0.1.0/src/fastdrf/convert.py +1327 -0
  36. django_fastdrf-0.1.0/src/fastdrf/inputs.py +891 -0
  37. django_fastdrf-0.1.0/src/fastdrf/list_serializers.py +112 -0
  38. django_fastdrf-0.1.0/src/fastdrf/management/__init__.py +0 -0
  39. django_fastdrf-0.1.0/src/fastdrf/management/commands/__init__.py +0 -0
  40. django_fastdrf-0.1.0/src/fastdrf/management/commands/fastdrf_convert.py +105 -0
  41. django_fastdrf-0.1.0/src/fastdrf/management/commands/fastdrf_inspect_serializers.py +257 -0
  42. django_fastdrf-0.1.0/src/fastdrf/mixins.py +124 -0
  43. django_fastdrf-0.1.0/src/fastdrf/msgspec/__init__.py +36 -0
  44. django_fastdrf-0.1.0/src/fastdrf/msgspec/compiler.py +220 -0
  45. django_fastdrf-0.1.0/src/fastdrf/msgspec/parsers.py +29 -0
  46. django_fastdrf-0.1.0/src/fastdrf/msgspec/renderers.py +87 -0
  47. django_fastdrf-0.1.0/src/fastdrf/msgspec/serializers.py +364 -0
  48. django_fastdrf-0.1.0/src/fastdrf/output.py +189 -0
  49. django_fastdrf-0.1.0/src/fastdrf/prefetch.py +315 -0
  50. django_fastdrf-0.1.0/src/fastdrf/py.typed +0 -0
  51. django_fastdrf-0.1.0/src/fastdrf/pydantic/__init__.py +21 -0
  52. django_fastdrf-0.1.0/src/fastdrf/pydantic/compiler.py +80 -0
  53. django_fastdrf-0.1.0/src/fastdrf/pydantic/serializers.py +341 -0
  54. django_fastdrf-0.1.0/src/fastdrf/renderers.py +84 -0
  55. django_fastdrf-0.1.0/src/fastdrf/response.py +259 -0
  56. django_fastdrf-0.1.0/src/fastdrf/serializers.py +228 -0
  57. django_fastdrf-0.1.0/src/fastdrf/settings.py +135 -0
  58. django_fastdrf-0.1.0/src/fastdrf/typed.py +705 -0
  59. django_fastdrf-0.1.0/src/fastdrf/utils.py +193 -0
  60. django_fastdrf-0.1.0/src/fastdrf/views.py +445 -0
  61. django_fastdrf-0.1.0/tests/__init__.py +1 -0
  62. django_fastdrf-0.1.0/tests/models.py +104 -0
  63. django_fastdrf-0.1.0/tests/settings.py +11 -0
  64. django_fastdrf-0.1.0/tests/test_batch_related_lookups.py +401 -0
  65. django_fastdrf-0.1.0/tests/test_checks.py +97 -0
  66. django_fastdrf-0.1.0/tests/test_classify.py +167 -0
  67. django_fastdrf-0.1.0/tests/test_codecs.py +251 -0
  68. django_fastdrf-0.1.0/tests/test_compiled_field_copy.py +307 -0
  69. django_fastdrf-0.1.0/tests/test_compiler.py +832 -0
  70. django_fastdrf-0.1.0/tests/test_compiler_compatibility.py +97 -0
  71. django_fastdrf-0.1.0/tests/test_compiler_completion.py +96 -0
  72. django_fastdrf-0.1.0/tests/test_compiler_datetimes.py +145 -0
  73. django_fastdrf-0.1.0/tests/test_compiler_native_values.py +208 -0
  74. django_fastdrf-0.1.0/tests/test_compiler_project_values.py +187 -0
  75. django_fastdrf-0.1.0/tests/test_compiler_relations.py +704 -0
  76. django_fastdrf-0.1.0/tests/test_compiler_sources.py +400 -0
  77. django_fastdrf-0.1.0/tests/test_compiler_to_many.py +370 -0
  78. django_fastdrf-0.1.0/tests/test_contracts.py +70 -0
  79. django_fastdrf-0.1.0/tests/test_convert.py +872 -0
  80. django_fastdrf-0.1.0/tests/test_differential_viewsets.py +505 -0
  81. django_fastdrf-0.1.0/tests/test_field_cache_language.py +148 -0
  82. django_fastdrf-0.1.0/tests/test_field_copy.py +140 -0
  83. django_fastdrf-0.1.0/tests/test_input_collections.py +224 -0
  84. django_fastdrf-0.1.0/tests/test_input_optimization.py +91 -0
  85. django_fastdrf-0.1.0/tests/test_inputs.py +1045 -0
  86. django_fastdrf-0.1.0/tests/test_inspect_command.py +437 -0
  87. django_fastdrf-0.1.0/tests/test_list_serializer_hook.py +55 -0
  88. django_fastdrf-0.1.0/tests/test_list_serializers.py +251 -0
  89. django_fastdrf-0.1.0/tests/test_loaded_columns.py +289 -0
  90. django_fastdrf-0.1.0/tests/test_msgspec_completion.py +84 -0
  91. django_fastdrf-0.1.0/tests/test_msgspec_renderer.py +147 -0
  92. django_fastdrf-0.1.0/tests/test_prefetch.py +417 -0
  93. django_fastdrf-0.1.0/tests/test_prefetch_list.py +206 -0
  94. django_fastdrf-0.1.0/tests/test_python_backend.py +144 -0
  95. django_fastdrf-0.1.0/tests/test_query_and_codec.py +180 -0
  96. django_fastdrf-0.1.0/tests/test_release_tool.py +68 -0
  97. django_fastdrf-0.1.0/tests/test_rendering.py +169 -0
  98. django_fastdrf-0.1.0/tests/test_response.py +592 -0
  99. django_fastdrf-0.1.0/tests/test_schema_serializers.py +951 -0
  100. django_fastdrf-0.1.0/tests/test_schema_serializers_msgspec.py +571 -0
  101. django_fastdrf-0.1.0/tests/test_schema_serializers_pydantic.py +643 -0
  102. django_fastdrf-0.1.0/tests/test_serializer_field_cache.py +674 -0
  103. django_fastdrf-0.1.0/tests/test_serializer_type_matrix.py +207 -0
  104. django_fastdrf-0.1.0/tests/test_serializers.py +143 -0
  105. django_fastdrf-0.1.0/tests/test_settings.py +115 -0
  106. django_fastdrf-0.1.0/tests/test_state_lifetimes.py +417 -0
  107. django_fastdrf-0.1.0/tests/test_threads.py +203 -0
  108. django_fastdrf-0.1.0/tests/test_views_compiled_writes.py +200 -0
  109. django_fastdrf-0.1.0/tests/test_views_data_response.py +241 -0
  110. django_fastdrf-0.1.0/tests/test_views_negotiation.py +410 -0
  111. django_fastdrf-0.1.0/tests/test_views_query_optimization.py +174 -0
  112. django_fastdrf-0.1.0/tests/test_views_request_plan.py +344 -0
  113. django_fastdrf-0.1.0/tests/threading.py +15 -0
  114. django_fastdrf-0.1.0/tests/urls.py +3 -0
  115. django_fastdrf-0.1.0/tools/check_wheel.py +40 -0
  116. django_fastdrf-0.1.0/tools/release.py +47 -0
  117. django_fastdrf-0.1.0/uv.lock +730 -0
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ .nox/
3
+ __pycache__/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .hypothesis/
7
+ .coverage*
8
+ htmlcov/
9
+ dist/
10
+ build/
11
+ .local/
@@ -0,0 +1,74 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file. The format
4
+ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the
5
+ project uses [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [0.1.0] - 2026-10-01
8
+
9
+ First release.
10
+
11
+ ### Added
12
+
13
+ Serializers:
14
+
15
+ - Serializer bases in `fastdrf.serializers` (`BaseSerializer`, `Serializer`,
16
+ `ListSerializer`, `ModelSerializer`, `HyperlinkedModelSerializer`) that
17
+ behave as DRF's with the default settings.
18
+ - Compiled serializer output with the `msgspec`, `pydantic` or
19
+ dependency-free `python` backend (`SERIALIZER_BACKEND`, or
20
+ `Meta.serializer_backend`). In `strict` parity the output equals DRF's,
21
+ including datetimes in the current time zone, quantized decimals,
22
+ primary-key and slug relations, file URLs, nested and to-many serializers.
23
+ `fast` parity accepts documented differences.
24
+ - `SERIALIZER_BACKEND_FALLBACK`: serializers the backend cannot compile are
25
+ represented by DRF, or raise with the reason.
26
+ - Input recognition for the msgspec and pydantic backends: JSON input that
27
+ DRF would accept unchanged is validated by a compiled class; all other
28
+ input, and every error, is DRF's.
29
+ - Field caching (`CACHE_SERIALIZER_FIELDS`) with `deepcopy`, `clone` and
30
+ `compiled` copy modes (`FIELD_COPY_MODE`), configurable per serializer and
31
+ per view.
32
+ - `default_list_serializer_class` for choosing the `many=True` list
33
+ serializer of a project base, and weakly bound list serializers in
34
+ `fastdrf.list_serializers`.
35
+ - Schema serializers: `MsgspecSerializer` and `PydanticSerializer`, defined by
36
+ a msgspec `Struct` or a pydantic model, with `fastdrf.typed.adapt`,
37
+ `schema_serializer`, `SchemaViewMixin` and the
38
+ `ALLOWED_SERIALIZER_BACKENDS` setting.
39
+
40
+ Queries:
41
+
42
+ - `QueryOptimizationMixin`, which derives `select_related` and
43
+ `prefetch_related` lookups from the serializer (`Meta.auto_prefetch`) and
44
+ applies explicit `Meta.prefetch` hints.
45
+ - `FETCH_MODE` for Django 6.1's `QuerySet.fetch_mode()`.
46
+ - `BATCH_RELATED_LOOKUPS`: one query for the items of
47
+ `PrimaryKeyRelatedField(many=True)` input.
48
+ - `PrefetchListSerializer` for loading data for all items of a list at once.
49
+
50
+ Views and responses:
51
+
52
+ - Dispatch mixins `NegotiationCacheMixin`, `RequestPlanMixin`,
53
+ `DataResponseMixin` and `DispatchOptimizationMixin`.
54
+ - `fastdrf.mixins.CreateModelMixin` and `UpdateModelMixin`, which produce
55
+ create and update responses with the serializer class's compiled encoder.
56
+ - `fastdrf.response.Response`, which releases its request objects when
57
+ closed, and `DataResponse`, rendered without DRF's template response.
58
+
59
+ Rendering and caching:
60
+
61
+ - `fastdrf.renderers.JSONRenderer`, DRF's renderer with a kept encoder.
62
+ - `MsgspecJSONRenderer` and `MsgspecJSONParser`.
63
+ - `MsgspecCodec` and `PydanticCodec` for Django's `RedisCache`.
64
+
65
+ Tooling:
66
+
67
+ - An optional Django app (`"fastdrf"`) with system checks `fastdrf.E001` to
68
+ `fastdrf.E006` and the management commands `fastdrf_inspect_serializers`
69
+ and `fastdrf_convert`.
70
+ - Support for Python 3.12 to 3.14, Django 5.2, 6.0 and 6.1, and DRF 3.16 to
71
+ 3.18, tested on free-threaded Python 3.14t too.
72
+ - Type information (`py.typed`).
73
+ - An example project, `examples/blog`, that serves the same API with DRF and
74
+ with fastdrf and tests both for identical responses.
@@ -0,0 +1,14 @@
1
+ # Code of conduct
2
+
3
+ This project follows the
4
+ [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
5
+ Everyone taking part in the project's issues, pull requests, discussions and
6
+ other spaces is expected to follow it.
7
+
8
+ ## Reporting
9
+
10
+ Report unacceptable behaviour to the project maintainer,
11
+ [@ctolon](https://github.com/ctolon), privately. Reports are reviewed
12
+ promptly and handled confidentially. The maintainer may remove content, or
13
+ restrict or end participation, as described in the Covenant's enforcement
14
+ guidelines.
@@ -0,0 +1,120 @@
1
+ # Contributing
2
+
3
+ Bug reports, questions and pull requests are welcome on
4
+ [GitHub](https://github.com/ctolon/django-fastdrf). For security issues,
5
+ follow the [security policy](SECURITY.md) instead of opening an issue.
6
+
7
+ ## Development setup
8
+
9
+ The project uses [uv](https://docs.astral.sh/uv/):
10
+
11
+ ```console
12
+ git clone https://github.com/ctolon/django-fastdrf.git
13
+ cd django-fastdrf
14
+ uv sync
15
+ ```
16
+
17
+ `uv sync` installs the package in editable mode with the `dev` dependency
18
+ group, which includes msgspec, pydantic, the test tools, ruff and nox.
19
+
20
+ ## Running the checks
21
+
22
+ ```console
23
+ uv run pytest # the test suite; warnings are errors
24
+ uv run ruff check . # lint
25
+ uv run ruff format --check . # formatting
26
+ ```
27
+
28
+ CI also measures coverage and requires at least 90% branch coverage:
29
+
30
+ ```console
31
+ uv run pytest --cov=fastdrf --cov-branch --cov-fail-under=90
32
+ ```
33
+
34
+ nox runs the suite against released Django and DRF versions. List the
35
+ sessions with `uv run nox -l`:
36
+
37
+ | Session | What it runs |
38
+ | --- | --- |
39
+ | `tests-<python>(django<x>-drf<y>)` | The suite on Python 3.12, 3.13 and 3.14 for each supported Django and DRF pair, for example `uv run nox -s "tests-3.14(django6.1-drf3.18)"`. |
40
+ | `freethreaded` | The suite on free-threaded Python 3.14t. |
41
+ | `tests_minimum` | The suite at the declared minimum versions of Django, DRF, msgspec and pydantic. |
42
+ | `tests_without_extras` | The `drf` and `python` backend tests with neither msgspec nor pydantic installed. |
43
+ | `differential(django<x>-drf<y>)` | The same requests to DRF's viewsets and to fastdrf's options, compared. |
44
+ | `lint` | `ruff check` and `ruff format --check`. |
45
+
46
+ To check the built package as CI does:
47
+
48
+ ```console
49
+ uv build
50
+ uvx twine check --strict dist/*
51
+ uv run --isolated --no-project --with dist/*.whl python tools/check_wheel.py
52
+ ```
53
+
54
+ `tools/check_wheel.py` imports every module of the installed wheel without
55
+ the optional extras and checks that the wheel carries the type marker and
56
+ the management commands.
57
+
58
+ The example project has its own tests:
59
+
60
+ ```console
61
+ cd examples/blog
62
+ uv run pytest
63
+ ```
64
+
65
+ ## Rules for changes
66
+
67
+ django-fastdrf exists to make DRF faster without changing what DRF does.
68
+ Changes follow these rules:
69
+
70
+ - Do not replace, patch or mutate Django or DRF classes or functions, at
71
+ import or at run time. Add subclasses, mixins or helpers that a project
72
+ selects, and keep DRF's method names, signatures and return types.
73
+ - Make every new optimization opt-in, with DRF's code as the fallback
74
+ wherever the optimization cannot show that its result equals DRF's.
75
+ - Identify framework code by class, as `fastdrf.utils` does, never by module
76
+ name. Treat any hook defined by a project class, or set on an instance, as
77
+ the project's.
78
+ - Write the test first. A change to output, input or queries needs a
79
+ differential test that compares the result with plain DRF, for invalid
80
+ input and custom hooks as well as for successful output, and a query-count
81
+ test where queries change. A change to shared state needs a concurrency
82
+ test.
83
+ - Keep caches bounded, keyed by classes or request-independent values, and
84
+ invalidated when the settings they read change.
85
+ - For a performance change, include the workload, the environment and
86
+ repeated measurements against the previous behaviour.
87
+
88
+ User-visible changes update the documentation in `docs/` and the unreleased
89
+ section at the top of `CHANGELOG.md`.
90
+
91
+ ## Pull requests
92
+
93
+ - Open pull requests against the `dev` branch. `main` receives `dev` at
94
+ release time; a workflow closes other pull requests into `main` with a
95
+ pointer to `dev`.
96
+ - CI runs lint, the full suite with coverage, the nox matrix and the
97
+ `freethreaded`, `tests_minimum`, `tests_without_extras` and `differential`
98
+ sessions, and builds and checks the package. A pull request from someone
99
+ other than the maintainer waits for the maintainer's approval before CI
100
+ runs.
101
+ - Keep a pull request to one change, and describe what it changes for users
102
+ and which DRF behaviour it preserves.
103
+
104
+ ## Releases
105
+
106
+ Releases are made by the maintainer:
107
+
108
+ 1. Set `version` in `pyproject.toml` and `__version__` in
109
+ `src/fastdrf/__init__.py` to the new version.
110
+ 2. Give the version's section of `CHANGELOG.md` its release date:
111
+ `## [X.Y.Z] - YYYY-MM-DD`.
112
+ 3. Merge `dev` into `main`.
113
+ 4. Run `python tools/release.py vX.Y.Z`, which checks that the three
114
+ versions agree and prints the release notes, then push the tag `vX.Y.Z`
115
+ on `main`.
116
+
117
+ The release workflow checks that the tag matches the package version and is
118
+ on `main`, builds and checks the distributions, publishes them to PyPI
119
+ through trusted publishing once the `pypi` environment is approved, and
120
+ creates the GitHub release with that version's changelog section as notes.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, ctolon
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,8 @@
1
+ django-fastdrf includes code derived from aiodrf, Copyright (c) ctolon,
2
+ distributed under the BSD 3-Clause license included in LICENSE.
3
+
4
+ The many_init list-construction protocol derives from Django REST framework:
5
+ Copyright (c) 2011-present, Encode OSS Ltd. All rights reserved.
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted under the BSD 3-Clause license in LICENSE. The original DRF
8
+ project is https://github.com/encode/django-rest-framework.
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.5
2
+ Name: django-fastdrf
3
+ Version: 0.1.0
4
+ Summary: Opt-in serializer and query optimizations for synchronous Django REST framework.
5
+ Project-URL: Homepage, https://github.com/ctolon/django-fastdrf
6
+ Project-URL: Documentation, https://github.com/ctolon/django-fastdrf/tree/main/docs
7
+ Project-URL: Changelog, https://github.com/ctolon/django-fastdrf/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/ctolon/django-fastdrf/issues
9
+ Project-URL: Source, https://github.com/ctolon/django-fastdrf
10
+ Author: Cevat Batuhan Tolon
11
+ License-Expression: BSD-3-Clause
12
+ License-File: LICENSE
13
+ License-File: NOTICE
14
+ Keywords: django,django-rest-framework,msgspec,performance,serializers
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Environment :: Web Environment
17
+ Classifier: Framework :: Django
18
+ Classifier: Framework :: Django :: 5.2
19
+ Classifier: Framework :: Django :: 6.0
20
+ Classifier: Framework :: Django :: 6.1
21
+ Classifier: Intended Audience :: Developers
22
+ Classifier: Operating System :: OS Independent
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3 :: Only
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
28
+ Classifier: Programming Language :: Python :: Free Threading :: 2 - Beta
29
+ Classifier: Topic :: Internet :: WWW/HTTP
30
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
+ Classifier: Typing :: Typed
32
+ Requires-Python: >=3.12
33
+ Requires-Dist: django>=5.2
34
+ Requires-Dist: djangorestframework>=3.16
35
+ Provides-Extra: msgspec
36
+ Requires-Dist: msgspec>=0.19; extra == 'msgspec'
37
+ Provides-Extra: pydantic
38
+ Requires-Dist: pydantic>=2.9; extra == 'pydantic'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # django-fastdrf
42
+
43
+ Opt-in serializer, query and response optimizations for synchronous
44
+ [Django REST framework](https://www.django-rest-framework.org/) projects.
45
+
46
+ django-fastdrf is for DRF projects that stay synchronous (WSGI, or ASGI with
47
+ synchronous views) and want less time per request without leaving DRF. It
48
+ adds subclasses, mixins and settings next to DRF's own classes. Each
49
+ optimization is enabled explicitly, per project, per view or per serializer,
50
+ and falls back to DRF's code wherever it cannot produce DRF's result.
51
+
52
+ It does not replace or patch any Django or DRF class, add async support, or
53
+ change DRF's validation errors.
54
+
55
+ ## Installation
56
+
57
+ ```console
58
+ pip install django-fastdrf
59
+ ```
60
+
61
+ The distribution is `django-fastdrf`; the import name is `fastdrf`. Two
62
+ extras install the optional backends:
63
+
64
+ ```console
65
+ pip install "django-fastdrf[msgspec]" # msgspec backend, renderer, parser, codec
66
+ pip install "django-fastdrf[pydantic]" # pydantic backend, schema serializers, codec
67
+ ```
68
+
69
+ Adding `"fastdrf"` to `INSTALLED_APPS` is optional. It registers system checks
70
+ and two management commands; everything else works without it.
71
+
72
+ ## Quick start
73
+
74
+ Use fastdrf's serializer bases and choose a backend for their output:
75
+
76
+ ```python
77
+ # settings.py
78
+ FASTDRF = {
79
+ "SERIALIZER_BACKEND": "msgspec", # or "pydantic", or "python" (no dependency)
80
+ "CACHE_SERIALIZER_FIELDS": True,
81
+ "FIELD_COPY_MODE": "compiled",
82
+ }
83
+ ```
84
+
85
+ ```python
86
+ # serializers.py
87
+ from fastdrf import serializers
88
+
89
+
90
+ class ArticleSerializer(serializers.ModelSerializer):
91
+ class Meta:
92
+ model = Article
93
+ fields = ["id", "title", "author", "published_at"]
94
+ auto_prefetch = True
95
+ ```
96
+
97
+ ```python
98
+ # views.py
99
+ from rest_framework import viewsets
100
+
101
+ from fastdrf.views import DispatchOptimizationMixin, QueryOptimizationMixin
102
+
103
+
104
+ class ArticleViewSet(
105
+ DispatchOptimizationMixin, QueryOptimizationMixin, viewsets.ModelViewSet
106
+ ):
107
+ queryset = Article.objects.all()
108
+ serializer_class = ArticleSerializer
109
+ ```
110
+
111
+ `.data`, `.is_valid()`, `.save()`, `many=True`, routers, pagination,
112
+ permissions and error responses are DRF's. With `"fastdrf"` in
113
+ `INSTALLED_APPS`, this command lists which serializers the backend compiles,
114
+ and why the others stay on DRF:
115
+
116
+ ```console
117
+ python manage.py fastdrf_inspect_serializers
118
+ ```
119
+
120
+ ## Features
121
+
122
+ Serialization:
123
+
124
+ - Compiled serializer output with the msgspec, pydantic or dependency-free
125
+ `python` backend, equal to DRF's `.data` in the default strict parity mode
126
+ ([serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#output-backends)).
127
+ - Input recognition: JSON input that DRF would accept unchanged is validated
128
+ by a compiled class; everything else, including every error, is DRF's
129
+ ([input recognition](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#input-recognition)).
130
+ - Cached field templates, copied per request with `deepcopy`, a scalar clone
131
+ or a compiled copy plan
132
+ ([field caching](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#field-caching-and-copying)).
133
+ - List serializers whose child refers to the list weakly
134
+ ([list serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#list-serializers)).
135
+ - Schema serializers: a msgspec `Struct` or a pydantic model as a DRF
136
+ serializer, and `SchemaViewMixin` for views
137
+ ([schema serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/schema-serializers.md)).
138
+
139
+ Queries:
140
+
141
+ - `select_related` and `prefetch_related` derived from the serializer by
142
+ `QueryOptimizationMixin`, explicit `Meta.prefetch` hints, Django 6.1's
143
+ `FETCH_MODE`, one query for many-valued primary-key input, and
144
+ `PrefetchListSerializer` for per-list enrichment
145
+ ([queries](https://github.com/ctolon/django-fastdrf/blob/main/docs/queries.md)).
146
+
147
+ Views and responses:
148
+
149
+ - Dispatch mixins that keep content negotiation and request construction
150
+ between requests, compiled create and update responses, a `Response` that
151
+ releases its request objects when closed, and `DataResponse`, rendered
152
+ without DRF's template response
153
+ ([views and responses](https://github.com/ctolon/django-fastdrf/blob/main/docs/views.md)).
154
+ - A `JSONRenderer` that keeps its encoder, msgspec's JSON renderer and
155
+ parser, and msgspec and pydantic codecs for Django's Redis cache
156
+ ([rendering and codecs](https://github.com/ctolon/django-fastdrf/blob/main/docs/rendering.md)).
157
+
158
+ Tooling:
159
+
160
+ - System checks for the `FASTDRF` setting and two management commands:
161
+ `fastdrf_inspect_serializers` and `fastdrf_convert`, which writes a schema
162
+ for a serializer or a serializer for a schema
163
+ ([commands](https://github.com/ctolon/django-fastdrf/blob/main/docs/commands.md)).
164
+
165
+ ## Guarantees and limits
166
+
167
+ - No Django or DRF class is replaced, patched or monkeypatched. fastdrf's
168
+ classes are subclasses and mixins that a project selects.
169
+ - Everything is opt-in. With the default settings, fastdrf's serializer bases
170
+ behave as DRF's.
171
+ - In strict parity, compiled output equals DRF's output; a field, value or
172
+ hook the compiler cannot prove equal keeps the serializer, or that one
173
+ source, on DRF. Input recognition never produces an error of its own.
174
+ - Synchronous only: no ORM call becomes asynchronous, and transactions,
175
+ authentication, permissions, throttling and pagination are DRF's and
176
+ Django's.
177
+ - Schema serializers, `fast` parity and the msgspec renderer have their own
178
+ documented output and validation rules; they are not DRF-identical by
179
+ design.
180
+ - A serializer instance belongs to one request; do not share it between
181
+ threads.
182
+
183
+ See [architecture](https://github.com/ctolon/django-fastdrf/blob/main/docs/architecture.md)
184
+ for how the caches are bounded and invalidated, and for the deliberate
185
+ differences.
186
+
187
+ ## Compatibility
188
+
189
+ | Django | DRF | Python |
190
+ | --- | --- | --- |
191
+ | 5.2 | 3.16, 3.17, 3.18 | 3.12, 3.13, 3.14 |
192
+ | 6.0 | 3.17, 3.18 | 3.12, 3.13, 3.14 |
193
+ | 6.1 | 3.18 | 3.12, 3.13, 3.14 |
194
+
195
+ The test suite also runs on free-threaded Python 3.14t (Django 6.1,
196
+ DRF 3.18) and at the declared minimum versions (Django 5.2, DRF 3.16,
197
+ msgspec 0.19, pydantic 2.9). `FETCH_MODE` needs Django 6.1.
198
+
199
+ ## Documentation
200
+
201
+ - [Documentation index](https://github.com/ctolon/django-fastdrf/blob/main/docs/README.md)
202
+ - [Configuration reference](https://github.com/ctolon/django-fastdrf/blob/main/docs/configuration.md)
203
+ - [Example project](https://github.com/ctolon/django-fastdrf/blob/main/examples/blog/README.md):
204
+ the same API with plain DRF and with fastdrf, with parity tests and a
205
+ measurement script
206
+ - [Changelog](https://github.com/ctolon/django-fastdrf/blob/main/CHANGELOG.md)
207
+ - [Contributing](https://github.com/ctolon/django-fastdrf/blob/main/CONTRIBUTING.md)
208
+ - [Security policy](https://github.com/ctolon/django-fastdrf/blob/main/SECURITY.md)
209
+
210
+ ## License
211
+
212
+ BSD 3-Clause. See
213
+ [LICENSE](https://github.com/ctolon/django-fastdrf/blob/main/LICENSE) and
214
+ [NOTICE](https://github.com/ctolon/django-fastdrf/blob/main/NOTICE): the optimizations derive from the aiodrf project, and the list-construction protocol from Django REST framework.
@@ -0,0 +1,174 @@
1
+ # django-fastdrf
2
+
3
+ Opt-in serializer, query and response optimizations for synchronous
4
+ [Django REST framework](https://www.django-rest-framework.org/) projects.
5
+
6
+ django-fastdrf is for DRF projects that stay synchronous (WSGI, or ASGI with
7
+ synchronous views) and want less time per request without leaving DRF. It
8
+ adds subclasses, mixins and settings next to DRF's own classes. Each
9
+ optimization is enabled explicitly, per project, per view or per serializer,
10
+ and falls back to DRF's code wherever it cannot produce DRF's result.
11
+
12
+ It does not replace or patch any Django or DRF class, add async support, or
13
+ change DRF's validation errors.
14
+
15
+ ## Installation
16
+
17
+ ```console
18
+ pip install django-fastdrf
19
+ ```
20
+
21
+ The distribution is `django-fastdrf`; the import name is `fastdrf`. Two
22
+ extras install the optional backends:
23
+
24
+ ```console
25
+ pip install "django-fastdrf[msgspec]" # msgspec backend, renderer, parser, codec
26
+ pip install "django-fastdrf[pydantic]" # pydantic backend, schema serializers, codec
27
+ ```
28
+
29
+ Adding `"fastdrf"` to `INSTALLED_APPS` is optional. It registers system checks
30
+ and two management commands; everything else works without it.
31
+
32
+ ## Quick start
33
+
34
+ Use fastdrf's serializer bases and choose a backend for their output:
35
+
36
+ ```python
37
+ # settings.py
38
+ FASTDRF = {
39
+ "SERIALIZER_BACKEND": "msgspec", # or "pydantic", or "python" (no dependency)
40
+ "CACHE_SERIALIZER_FIELDS": True,
41
+ "FIELD_COPY_MODE": "compiled",
42
+ }
43
+ ```
44
+
45
+ ```python
46
+ # serializers.py
47
+ from fastdrf import serializers
48
+
49
+
50
+ class ArticleSerializer(serializers.ModelSerializer):
51
+ class Meta:
52
+ model = Article
53
+ fields = ["id", "title", "author", "published_at"]
54
+ auto_prefetch = True
55
+ ```
56
+
57
+ ```python
58
+ # views.py
59
+ from rest_framework import viewsets
60
+
61
+ from fastdrf.views import DispatchOptimizationMixin, QueryOptimizationMixin
62
+
63
+
64
+ class ArticleViewSet(
65
+ DispatchOptimizationMixin, QueryOptimizationMixin, viewsets.ModelViewSet
66
+ ):
67
+ queryset = Article.objects.all()
68
+ serializer_class = ArticleSerializer
69
+ ```
70
+
71
+ `.data`, `.is_valid()`, `.save()`, `many=True`, routers, pagination,
72
+ permissions and error responses are DRF's. With `"fastdrf"` in
73
+ `INSTALLED_APPS`, this command lists which serializers the backend compiles,
74
+ and why the others stay on DRF:
75
+
76
+ ```console
77
+ python manage.py fastdrf_inspect_serializers
78
+ ```
79
+
80
+ ## Features
81
+
82
+ Serialization:
83
+
84
+ - Compiled serializer output with the msgspec, pydantic or dependency-free
85
+ `python` backend, equal to DRF's `.data` in the default strict parity mode
86
+ ([serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#output-backends)).
87
+ - Input recognition: JSON input that DRF would accept unchanged is validated
88
+ by a compiled class; everything else, including every error, is DRF's
89
+ ([input recognition](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#input-recognition)).
90
+ - Cached field templates, copied per request with `deepcopy`, a scalar clone
91
+ or a compiled copy plan
92
+ ([field caching](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#field-caching-and-copying)).
93
+ - List serializers whose child refers to the list weakly
94
+ ([list serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/serializers.md#list-serializers)).
95
+ - Schema serializers: a msgspec `Struct` or a pydantic model as a DRF
96
+ serializer, and `SchemaViewMixin` for views
97
+ ([schema serializers](https://github.com/ctolon/django-fastdrf/blob/main/docs/schema-serializers.md)).
98
+
99
+ Queries:
100
+
101
+ - `select_related` and `prefetch_related` derived from the serializer by
102
+ `QueryOptimizationMixin`, explicit `Meta.prefetch` hints, Django 6.1's
103
+ `FETCH_MODE`, one query for many-valued primary-key input, and
104
+ `PrefetchListSerializer` for per-list enrichment
105
+ ([queries](https://github.com/ctolon/django-fastdrf/blob/main/docs/queries.md)).
106
+
107
+ Views and responses:
108
+
109
+ - Dispatch mixins that keep content negotiation and request construction
110
+ between requests, compiled create and update responses, a `Response` that
111
+ releases its request objects when closed, and `DataResponse`, rendered
112
+ without DRF's template response
113
+ ([views and responses](https://github.com/ctolon/django-fastdrf/blob/main/docs/views.md)).
114
+ - A `JSONRenderer` that keeps its encoder, msgspec's JSON renderer and
115
+ parser, and msgspec and pydantic codecs for Django's Redis cache
116
+ ([rendering and codecs](https://github.com/ctolon/django-fastdrf/blob/main/docs/rendering.md)).
117
+
118
+ Tooling:
119
+
120
+ - System checks for the `FASTDRF` setting and two management commands:
121
+ `fastdrf_inspect_serializers` and `fastdrf_convert`, which writes a schema
122
+ for a serializer or a serializer for a schema
123
+ ([commands](https://github.com/ctolon/django-fastdrf/blob/main/docs/commands.md)).
124
+
125
+ ## Guarantees and limits
126
+
127
+ - No Django or DRF class is replaced, patched or monkeypatched. fastdrf's
128
+ classes are subclasses and mixins that a project selects.
129
+ - Everything is opt-in. With the default settings, fastdrf's serializer bases
130
+ behave as DRF's.
131
+ - In strict parity, compiled output equals DRF's output; a field, value or
132
+ hook the compiler cannot prove equal keeps the serializer, or that one
133
+ source, on DRF. Input recognition never produces an error of its own.
134
+ - Synchronous only: no ORM call becomes asynchronous, and transactions,
135
+ authentication, permissions, throttling and pagination are DRF's and
136
+ Django's.
137
+ - Schema serializers, `fast` parity and the msgspec renderer have their own
138
+ documented output and validation rules; they are not DRF-identical by
139
+ design.
140
+ - A serializer instance belongs to one request; do not share it between
141
+ threads.
142
+
143
+ See [architecture](https://github.com/ctolon/django-fastdrf/blob/main/docs/architecture.md)
144
+ for how the caches are bounded and invalidated, and for the deliberate
145
+ differences.
146
+
147
+ ## Compatibility
148
+
149
+ | Django | DRF | Python |
150
+ | --- | --- | --- |
151
+ | 5.2 | 3.16, 3.17, 3.18 | 3.12, 3.13, 3.14 |
152
+ | 6.0 | 3.17, 3.18 | 3.12, 3.13, 3.14 |
153
+ | 6.1 | 3.18 | 3.12, 3.13, 3.14 |
154
+
155
+ The test suite also runs on free-threaded Python 3.14t (Django 6.1,
156
+ DRF 3.18) and at the declared minimum versions (Django 5.2, DRF 3.16,
157
+ msgspec 0.19, pydantic 2.9). `FETCH_MODE` needs Django 6.1.
158
+
159
+ ## Documentation
160
+
161
+ - [Documentation index](https://github.com/ctolon/django-fastdrf/blob/main/docs/README.md)
162
+ - [Configuration reference](https://github.com/ctolon/django-fastdrf/blob/main/docs/configuration.md)
163
+ - [Example project](https://github.com/ctolon/django-fastdrf/blob/main/examples/blog/README.md):
164
+ the same API with plain DRF and with fastdrf, with parity tests and a
165
+ measurement script
166
+ - [Changelog](https://github.com/ctolon/django-fastdrf/blob/main/CHANGELOG.md)
167
+ - [Contributing](https://github.com/ctolon/django-fastdrf/blob/main/CONTRIBUTING.md)
168
+ - [Security policy](https://github.com/ctolon/django-fastdrf/blob/main/SECURITY.md)
169
+
170
+ ## License
171
+
172
+ BSD 3-Clause. See
173
+ [LICENSE](https://github.com/ctolon/django-fastdrf/blob/main/LICENSE) and
174
+ [NOTICE](https://github.com/ctolon/django-fastdrf/blob/main/NOTICE): the optimizations derive from the aiodrf project, and the list-construction protocol from Django REST framework.
@@ -0,0 +1,30 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are made for the latest release of django-fastdrf. Upgrade to
6
+ it before reporting an issue, if you can.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Report a suspected vulnerability privately through GitHub's private
11
+ vulnerability reporting:
12
+ [open a report](https://github.com/ctolon/django-fastdrf/security/advisories/new)
13
+ on the repository's Security tab. Do not open a public issue or pull request
14
+ for it.
15
+
16
+ Include the affected version, the Django, DRF and Python versions, the
17
+ settings and classes involved, and the steps to reproduce. Do not include
18
+ credentials, personal data or production data.
19
+
20
+ You will receive an acknowledgement, and the advisory will be published with
21
+ the fixed release once a fix is available.
22
+
23
+ ## Scope
24
+
25
+ django-fastdrf changes how DRF serializes, validates, loads related objects
26
+ and renders. It does not replace authentication, permissions, throttling,
27
+ queryset scoping or validation that a project defines. A report is in scope
28
+ when an optimization makes a response, a validation result or a query differ
29
+ from what DRF would produce with the same project code, or exposes data
30
+ across requests.