django-ninja-aio-crud 2.18.1__tar.gz → 2.18.2__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.
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/CHANGELOG.md +89 -8
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/PKG-INFO +1 -1
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/__init__.py +1 -1
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/models/utils.py +3 -80
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/models/test_models_extra.py +0 -22
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/dependabot.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/coverage.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/docs.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/performance.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/publish.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.gitignore +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.pre-commit-config.yaml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/CLAUDE.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/LICENSE +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/README.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/CNAME +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/authentication.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/model_serializer.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/model_util.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/serializers.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/validators.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/pagination.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/renderers/orjson_renderer.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/views/api_view.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/views/api_view_set.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/views/decorators.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/views/mixins.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/auth.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/contributing.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/extra.css +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-create-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-delete-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-list-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-retrieve-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/images/index/foo-index-update-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/installation.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/quick_start.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/quick_start_serializer.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/bar-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/favicon.ico +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/foo-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/logo-full.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/logo.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/images/model_util/foo-reverse-relations-swagger.png +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/index.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/performance.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/release_notes.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/requirements.txt +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/authentication.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/crud.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/filtering.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/model.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/serializer.md +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/main.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/mkdocs.yml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/auth.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/decorators/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/decorators/operations.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/decorators/views.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/exceptions.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/factory/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/factory/operations.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/helpers/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/helpers/api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/helpers/query.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/models/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/models/serializers.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/parsers.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/renders.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/schemas/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/schemas/api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/schemas/filters.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/schemas/generics.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/schemas/helpers.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/types.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/views/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/views/api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/views/mixins.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/overrides/main.html +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/overrides/partials/announce.html +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/pyproject.toml +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/requirements.dev.txt +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/run-local-coverage.sh +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/run-performance.sh +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/test_decorators.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/test_exceptions_api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/test_renderer_parser.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/generics/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/generics/literals.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/generics/models.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/generics/request.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/generics/views.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/helpers/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/helpers/test_many_to_many_api.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/models/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/models/test_model_util.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/check_regression.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/generate_report.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/test_performance.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_app/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_app/models.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_app/schema.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_app/serializers.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_app/views.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_auth.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_decorators.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_exceptions.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_query_util.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_serializers.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/test_settings.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/views/__init__.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/views/test_views.py +0 -0
- {django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/views/test_viewset.py +0 -0
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# 📋 Release Notes
|
|
2
2
|
|
|
3
|
+
## 🏷️ [v2.18.2] - 2026-02-02
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 🔧 Improvements
|
|
8
|
+
|
|
9
|
+
#### ✨ Removed Redundant Input Validation
|
|
10
|
+
> `ninja_aio/models/utils.py`
|
|
11
|
+
|
|
12
|
+
Removed redundant input field validation logic since Pydantic already validates all inputs before they reach the payload processing stage. This simplifies the codebase and properly handles field aliases and custom fields.
|
|
13
|
+
|
|
14
|
+
**Removed methods:**
|
|
15
|
+
|
|
16
|
+
| Method | Previous Line | Why Removed |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `_validate_input_fields()` | 746-782 | Redundant - Pydantic validates all inputs during schema deserialization |
|
|
19
|
+
| `get_valid_input_fields()` | 198-237 | Only used by removed `_validate_input_fields()` method |
|
|
20
|
+
|
|
21
|
+
**Updated method:**
|
|
22
|
+
- `parse_input_data()` - Removed call to `_validate_input_fields()` and added clarifying comment that Pydantic handles all validation
|
|
23
|
+
|
|
24
|
+
**Why this improves the code:**
|
|
25
|
+
|
|
26
|
+
Since Django Ninja uses Pydantic to validate all inputs against generated schemas:
|
|
27
|
+
- ✅ Custom fields (defined via `custom_fields` parameter) are validated by Pydantic
|
|
28
|
+
- ✅ Field aliases are properly handled by Pydantic during deserialization
|
|
29
|
+
- ✅ By the time `parse_input_data()` receives the `Schema` instance, all validation has already occurred
|
|
30
|
+
- ✅ `model_dump()` simply converts the validated instance to a dict with proper field names
|
|
31
|
+
|
|
32
|
+
The removed validation was:
|
|
33
|
+
- ❌ Redundant (Pydantic already validated)
|
|
34
|
+
- ❌ Incomplete (couldn't properly handle all Pydantic features like aliases)
|
|
35
|
+
- ❌ Assuming custom fields and aliases couldn't be used in requests
|
|
36
|
+
|
|
37
|
+
**Example of what now works correctly:**
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from pydantic import Field
|
|
41
|
+
from ninja_aio.models import Serializer, serializers
|
|
42
|
+
|
|
43
|
+
class UserSerializer(Serializer):
|
|
44
|
+
class Meta:
|
|
45
|
+
model = User
|
|
46
|
+
schema_in = serializers.SchemaModelConfig(
|
|
47
|
+
fields=["username", "email"],
|
|
48
|
+
custom_fields=[
|
|
49
|
+
("display_name", str, Field(alias="displayName")) # Alias support
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Input with alias now works properly:
|
|
54
|
+
# {"username": "john", "email": "john@example.com", "displayName": "John Doe"}
|
|
55
|
+
# Pydantic handles the alias → Validation passes → No redundant checks
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 🧪 Tests
|
|
61
|
+
|
|
62
|
+
#### `ModelUtilHelperMethodsTestCase` — Removed 3 tests
|
|
63
|
+
|
|
64
|
+
**Removed tests:**
|
|
65
|
+
|
|
66
|
+
| Test | Reason |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `test_validate_input_fields_valid_fields` | Method `_validate_input_fields` no longer exists |
|
|
69
|
+
| `test_validate_input_fields_invalid_fields` | Method `_validate_input_fields` no longer exists |
|
|
70
|
+
| `test_validate_input_fields_skips_custom_fields` | Method `_validate_input_fields` no longer exists |
|
|
71
|
+
|
|
72
|
+
**Test results:**
|
|
73
|
+
- ✅ 608 tests pass (down from 611)
|
|
74
|
+
- ✅ 100% coverage maintained on `ninja_aio/models/utils.py`
|
|
75
|
+
- ✅ 99% overall coverage maintained
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 🎯 Summary
|
|
80
|
+
|
|
81
|
+
**Django Ninja Aio CRUD v2.18.2** is a code quality improvement release that removes redundant validation logic. By trusting Pydantic's built-in validation, the codebase is simplified while properly supporting all Pydantic features including field aliases and custom fields. This change has no impact on end users since Pydantic was already handling validation - we simply removed the redundant secondary validation that was incomplete and caused issues with aliases.
|
|
82
|
+
|
|
83
|
+
**Key benefits:**
|
|
84
|
+
- 🧹 **Simpler Code** — Removed 70+ lines of redundant validation logic
|
|
85
|
+
- ✅ **Proper Alias Support** — Field aliases now work correctly without workarounds
|
|
86
|
+
- 🎯 **Trust the Framework** — Pydantic handles all input validation; no redundant checks needed
|
|
87
|
+
- 🔒 **Same Security** — No security impact since Pydantic validation was already the primary defense
|
|
88
|
+
- 🧪 **100% Coverage** — Maintained complete test coverage across the codebase
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
3
92
|
## 🏷️ [v2.18.1] - 2026-02-01
|
|
4
93
|
|
|
5
94
|
---
|
|
@@ -365,14 +454,6 @@ Added comprehensive tests for all new functionality:
|
|
|
365
454
|
|
|
366
455
|
Added comprehensive performance benchmarking infrastructure for monitoring framework performance during development.
|
|
367
456
|
|
|
368
|
-
**New files:**
|
|
369
|
-
- `tests/performance/__init__.py` - Performance test package
|
|
370
|
-
- `tests/performance/test_performance.py` - 482 lines, 19 benchmarks
|
|
371
|
-
- `tests/performance/generate_report.py` - 511 lines, interactive HTML report generator
|
|
372
|
-
- `tests/performance/check_regression.py` - 172 lines, regression detection
|
|
373
|
-
- `run-performance.sh` - Shell script to run benchmarks
|
|
374
|
-
- `.github/workflows/performance.yml` - CI workflow for automated benchmarking
|
|
375
|
-
|
|
376
457
|
**Benchmark categories:**
|
|
377
458
|
- Schema generation (4 tests)
|
|
378
459
|
- Serialization (4 tests)
|
|
@@ -195,46 +195,6 @@ class ModelUtil:
|
|
|
195
195
|
"""
|
|
196
196
|
return [field.name for field in self.model._meta.get_fields()]
|
|
197
197
|
|
|
198
|
-
def get_valid_input_fields(
|
|
199
|
-
self, is_serializer: bool, serializer: "ModelSerializer | None" = None
|
|
200
|
-
) -> set[str]:
|
|
201
|
-
"""
|
|
202
|
-
Get allowlist of valid field names for input validation.
|
|
203
|
-
|
|
204
|
-
Security: Prevents field injection by returning only fields that should
|
|
205
|
-
be accepted from user input.
|
|
206
|
-
|
|
207
|
-
Parameters
|
|
208
|
-
----------
|
|
209
|
-
is_serializer : bool
|
|
210
|
-
Whether using a ModelSerializer
|
|
211
|
-
serializer : ModelSerializer, optional
|
|
212
|
-
Serializer instance if applicable
|
|
213
|
-
|
|
214
|
-
Returns
|
|
215
|
-
-------
|
|
216
|
-
set[str]
|
|
217
|
-
Set of valid field names that can be accepted in input payloads
|
|
218
|
-
"""
|
|
219
|
-
valid_fields = set(self.model_fields)
|
|
220
|
-
|
|
221
|
-
# If using a serializer, also include custom fields
|
|
222
|
-
if is_serializer and serializer:
|
|
223
|
-
# Get all custom fields defined in the serializer
|
|
224
|
-
try:
|
|
225
|
-
# Custom fields are those that are not model fields but are defined
|
|
226
|
-
# in the serializer configuration
|
|
227
|
-
for schema_type in ['create', 'update', 'read', 'detail']:
|
|
228
|
-
try:
|
|
229
|
-
schema_fields = serializer.get_fields(schema_type)
|
|
230
|
-
if schema_fields:
|
|
231
|
-
valid_fields.update(schema_fields)
|
|
232
|
-
except (AttributeError, TypeError):
|
|
233
|
-
continue
|
|
234
|
-
except (AttributeError, TypeError):
|
|
235
|
-
pass
|
|
236
|
-
|
|
237
|
-
return valid_fields
|
|
238
198
|
|
|
239
199
|
@property
|
|
240
200
|
def model_name(self) -> str:
|
|
@@ -743,43 +703,6 @@ class ModelUtil:
|
|
|
743
703
|
obj = await self.get_object(request, query_data=query_data, is_for=is_for)
|
|
744
704
|
return await self._bump_object_from_schema(obj, obj_schema)
|
|
745
705
|
|
|
746
|
-
def _validate_input_fields(
|
|
747
|
-
self, payload: dict, is_serializer: bool, serializer
|
|
748
|
-
) -> None:
|
|
749
|
-
"""
|
|
750
|
-
Validate non-custom payload keys against model fields.
|
|
751
|
-
|
|
752
|
-
Parameters
|
|
753
|
-
----------
|
|
754
|
-
payload : dict
|
|
755
|
-
Input payload to validate.
|
|
756
|
-
is_serializer : bool
|
|
757
|
-
Whether using a ModelSerializer.
|
|
758
|
-
serializer : ModelSerializer | Serializer
|
|
759
|
-
Serializer instance if applicable.
|
|
760
|
-
|
|
761
|
-
Raises
|
|
762
|
-
------
|
|
763
|
-
SerializeError
|
|
764
|
-
If invalid field names are found in payload.
|
|
765
|
-
"""
|
|
766
|
-
invalid_fields = []
|
|
767
|
-
for key in payload.keys():
|
|
768
|
-
# Skip custom fields - they're validated by Pydantic schema
|
|
769
|
-
if is_serializer and serializer.is_custom(key):
|
|
770
|
-
continue
|
|
771
|
-
# Validate non-custom fields exist on the model
|
|
772
|
-
if key not in self.model_fields:
|
|
773
|
-
invalid_fields.append(key)
|
|
774
|
-
|
|
775
|
-
if invalid_fields:
|
|
776
|
-
raise SerializeError(
|
|
777
|
-
{
|
|
778
|
-
"detail": f"Invalid field names in payload: {', '.join(sorted(invalid_fields))}",
|
|
779
|
-
"invalid_fields": sorted(invalid_fields),
|
|
780
|
-
},
|
|
781
|
-
400,
|
|
782
|
-
)
|
|
783
706
|
|
|
784
707
|
def _collect_custom_and_optional_fields(
|
|
785
708
|
self, payload: dict, is_serializer: bool, serializer
|
|
@@ -888,7 +811,7 @@ class ModelUtil:
|
|
|
888
811
|
|
|
889
812
|
Steps
|
|
890
813
|
-----
|
|
891
|
-
- Validate fields against
|
|
814
|
+
- Validate fields against schema (including aliases and custom fields).
|
|
892
815
|
- Strip custom fields (retain separately).
|
|
893
816
|
- Drop optional fields with None (ModelSerializer only).
|
|
894
817
|
- Decode BinaryField base64 values.
|
|
@@ -917,8 +840,8 @@ class ModelUtil:
|
|
|
917
840
|
)
|
|
918
841
|
serializer = self.serializer if self.with_serializer else self.model
|
|
919
842
|
|
|
920
|
-
#
|
|
921
|
-
|
|
843
|
+
# Note: Field validation is handled by Pydantic during schema deserialization
|
|
844
|
+
# No additional validation needed here since data is already a validated Schema instance
|
|
922
845
|
|
|
923
846
|
# Collect custom and optional fields
|
|
924
847
|
customs, optionals = self._collect_custom_and_optional_fields(
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/models/test_models_extra.py
RENAMED
|
@@ -537,28 +537,6 @@ class ModelUtilHelperMethodsTestCase(TestCase):
|
|
|
537
537
|
cls.util_custom = ModelUtil(CustomOptionalSerializer)
|
|
538
538
|
cls.util_plain = ModelUtil(app_models.TestModelSerializer)
|
|
539
539
|
|
|
540
|
-
def test_validate_input_fields_valid_fields(self):
|
|
541
|
-
"""_validate_input_fields should not raise for valid fields."""
|
|
542
|
-
payload = {"name": "test", "description": "desc"}
|
|
543
|
-
# Should not raise
|
|
544
|
-
self.util_plain._validate_input_fields(payload, False, None)
|
|
545
|
-
|
|
546
|
-
def test_validate_input_fields_invalid_fields(self):
|
|
547
|
-
"""_validate_input_fields should raise SerializeError for invalid fields."""
|
|
548
|
-
payload = {"name": "test", "invalid_field": "value"}
|
|
549
|
-
with self.assertRaises(SerializeError) as cm:
|
|
550
|
-
self.util_plain._validate_input_fields(payload, False, None)
|
|
551
|
-
error_data = cm.exception.error
|
|
552
|
-
self.assertIn("invalid_fields", error_data)
|
|
553
|
-
self.assertIn("invalid_field", error_data["invalid_fields"])
|
|
554
|
-
|
|
555
|
-
def test_validate_input_fields_skips_custom_fields(self):
|
|
556
|
-
"""_validate_input_fields should skip custom fields when using serializer."""
|
|
557
|
-
payload = {"name": "test", "extra": "custom"}
|
|
558
|
-
# Should not raise because 'extra' is a custom field
|
|
559
|
-
self.util_custom._validate_input_fields(
|
|
560
|
-
payload, True, CustomOptionalSerializer
|
|
561
|
-
)
|
|
562
540
|
|
|
563
541
|
def test_collect_custom_and_optional_fields_with_serializer(self):
|
|
564
542
|
"""_collect_custom_and_optional_fields should collect custom and optional fields."""
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/coverage.yml
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/.github/workflows/performance.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/model_serializer.md
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/models/serializers.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/renderers/orjson_renderer.md
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/api/views/api_view_set.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/installation.md
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/getting_started/quick_start.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/docs/tutorial/authentication.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/decorators/__init__.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/decorators/operations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/factory/operations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/ninja_aio/models/serializers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/overrides/partials/announce.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/test_exceptions_api.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/core/test_renderer_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/helpers/test_many_to_many_api.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/models/test_model_util.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/check_regression.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/generate_report.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.18.1 → django_ninja_aio_crud-2.18.2}/tests/performance/test_performance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|