django-ninja-aio-crud 2.12.0__tar.gz → 2.12.1__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.

Potentially problematic release.


This version of django-ninja-aio-crud might be problematic. Click here for more details.

Files changed (103) hide show
  1. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.github/workflows/docs.yml +2 -0
  2. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/PKG-INFO +1 -1
  3. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/__init__.py +1 -1
  4. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/helpers/query.py +6 -1
  5. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_query_util.py +54 -0
  6. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.github/dependabot.yml +0 -0
  7. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.github/workflows/coverage.yml +0 -0
  8. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.github/workflows/publish.yml +0 -0
  9. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.gitignore +0 -0
  10. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/.pre-commit-config.yaml +0 -0
  11. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/LICENSE +0 -0
  12. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/README.md +0 -0
  13. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/CNAME +0 -0
  14. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/authentication.md +0 -0
  15. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/models/model_serializer.md +0 -0
  16. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/models/model_util.md +0 -0
  17. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/models/serializers.md +0 -0
  18. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/pagination.md +0 -0
  19. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/renderers/orjson_renderer.md +0 -0
  20. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/views/api_view.md +0 -0
  21. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/views/api_view_set.md +0 -0
  22. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/views/decorators.md +0 -0
  23. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/api/views/mixins.md +0 -0
  24. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/auth.md +0 -0
  25. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/contributing.md +0 -0
  26. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/extra.css +0 -0
  27. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-create-swagger.png +0 -0
  28. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-delete-swagger.png +0 -0
  29. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-list-swagger.png +0 -0
  30. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-retrieve-swagger.png +0 -0
  31. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-swagger.png +0 -0
  32. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/images/index/foo-index-update-swagger.png +0 -0
  33. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/installation.md +0 -0
  34. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/getting_started/quick_start.md +0 -0
  35. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/images/bar-swagger.png +0 -0
  36. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/images/favicon.ico +0 -0
  37. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/images/foo-swagger.png +0 -0
  38. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/images/logo.png +0 -0
  39. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/images/model_util/foo-reverse-relations-swagger.png +0 -0
  40. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/index.md +0 -0
  41. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/release_notes.md +0 -0
  42. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/requirements.txt +0 -0
  43. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/tutorial/authentication.md +0 -0
  44. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/tutorial/crud.md +0 -0
  45. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/tutorial/filtering.md +0 -0
  46. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/docs/tutorial/model.md +0 -0
  47. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/main.py +0 -0
  48. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/mkdocs.yml +0 -0
  49. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/api.py +0 -0
  50. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/auth.py +0 -0
  51. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/decorators/__init__.py +0 -0
  52. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/decorators/operations.py +0 -0
  53. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/decorators/views.py +0 -0
  54. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/exceptions.py +0 -0
  55. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/factory/__init__.py +0 -0
  56. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/factory/operations.py +0 -0
  57. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/helpers/__init__.py +0 -0
  58. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/helpers/api.py +0 -0
  59. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/models/__init__.py +0 -0
  60. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/models/serializers.py +0 -0
  61. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/models/utils.py +0 -0
  62. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/parsers.py +0 -0
  63. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/renders.py +0 -0
  64. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/schemas/__init__.py +0 -0
  65. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/schemas/api.py +0 -0
  66. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/schemas/filters.py +0 -0
  67. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/schemas/generics.py +0 -0
  68. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/schemas/helpers.py +0 -0
  69. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/types.py +0 -0
  70. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/views/__init__.py +0 -0
  71. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/views/api.py +0 -0
  72. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/ninja_aio/views/mixins.py +0 -0
  73. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/pyproject.toml +0 -0
  74. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/requirements.dev.txt +0 -0
  75. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/run-local-coverage.sh +0 -0
  76. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/__init__.py +0 -0
  77. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/core/__init__.py +0 -0
  78. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/core/test_decorators.py +0 -0
  79. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/core/test_exceptions_api.py +0 -0
  80. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/core/test_renderer_parser.py +0 -0
  81. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/generics/__init__.py +0 -0
  82. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/generics/literals.py +0 -0
  83. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/generics/models.py +0 -0
  84. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/generics/request.py +0 -0
  85. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/generics/views.py +0 -0
  86. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/helpers/__init__.py +0 -0
  87. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/helpers/test_many_to_many_api.py +0 -0
  88. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/models/__init__.py +0 -0
  89. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/models/test_model_util.py +0 -0
  90. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/models/test_models_extra.py +0 -0
  91. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_app/__init__.py +0 -0
  92. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_app/models.py +0 -0
  93. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_app/schema.py +0 -0
  94. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_app/serializers.py +0 -0
  95. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_app/views.py +0 -0
  96. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_auth.py +0 -0
  97. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_decorators.py +0 -0
  98. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_exceptions.py +0 -0
  99. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_serializers.py +0 -0
  100. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/test_settings.py +0 -0
  101. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/views/__init__.py +0 -0
  102. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/views/test_views.py +0 -0
  103. {django_ninja_aio_crud-2.12.0 → django_ninja_aio_crud-2.12.1}/tests/views/test_viewset.py +0 -0
@@ -24,6 +24,7 @@ on:
24
24
  - "2.9"
25
25
  - "2.10"
26
26
  - "2.11"
27
+ - "2.12"
27
28
  make_latest:
28
29
  description: 'Set as "latest" and default?'
29
30
  type: boolean
@@ -51,6 +52,7 @@ on:
51
52
  - "2.9"
52
53
  - "2.10"
53
54
  - "2.11"
55
+ - "2.12"
54
56
  delete_confirm:
55
57
  description: 'Confirm deletion of the selected version'
56
58
  type: boolean
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-ninja-aio-crud
3
- Version: 2.12.0
3
+ Version: 2.12.1
4
4
  Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10, <3.15
@@ -1,6 +1,6 @@
1
1
  """Django Ninja AIO CRUD - Rest Framework"""
2
2
 
3
- __version__ = "2.12.0"
3
+ __version__ = "2.12.1"
4
4
 
5
5
  from .api import NinjaAIO
6
6
 
@@ -78,6 +78,11 @@ class QueryUtil:
78
78
  self.detail_config: ModelQuerySetSchema = self._configs.get(
79
79
  self.SCOPES.DETAIL, ModelQuerySetSchema()
80
80
  )
81
+ # Fallback detail config to read config if not explicitly set
82
+ if not self.detail_config.select_related:
83
+ self.detail_config.select_related = self.read_config.select_related.copy()
84
+ if not self.detail_config.prefetch_related:
85
+ self.detail_config.prefetch_related = self.read_config.prefetch_related.copy()
81
86
 
82
87
  def _get_config(self, conf_name: str) -> ModelQuerySetSchema:
83
88
  """Helper method to retrieve configuration attributes."""
@@ -103,7 +108,7 @@ class QueryUtil:
103
108
  raise ValueError(
104
109
  f"Invalid scope '{scope}' for QueryUtil. Supported scopes: {valid_scopes}"
105
110
  )
106
- config = self._configs.get(scope, ModelQuerySetSchema())
111
+ config: ModelQuerySetSchema = self._configs.get(scope, ModelQuerySetSchema())
107
112
  if config.select_related:
108
113
  queryset = queryset.select_related(*config.select_related)
109
114
  if config.prefetch_related:
@@ -96,6 +96,60 @@ class QueryUtilDedicatedTestCase(TestCase):
96
96
  m_pref.assert_not_called()
97
97
 
98
98
 
99
+ def test_detail_scope_fallback_to_read_select_related(self):
100
+ """Test that DETAIL scope falls back to READ's select_related when not configured."""
101
+ # TestModelSerializerForeignKey has read config but no detail config
102
+ qs = app_models.TestModelSerializerForeignKey.objects.all()
103
+ with mock.patch(
104
+ "django.db.models.query.QuerySet.select_related",
105
+ side_effect=lambda self, *args: self,
106
+ autospec=True,
107
+ ) as m_sel:
108
+ _ = self.query_util_fk.apply_queryset_optimizations(
109
+ qs, self.query_util_fk.SCOPES.DETAIL
110
+ )
111
+ sel_args = m_sel.call_args[0][1:]
112
+ # Should use read_config's select_related as fallback
113
+ self.assertEqual(sel_args, ("test_model_serializer",))
114
+
115
+ def test_detail_scope_fallback_to_read_prefetch_related(self):
116
+ """Test that DETAIL scope falls back to READ's prefetch_related when not configured."""
117
+ # TestModelSerializerManyToMany has queryset_request with prefetch but no detail
118
+ # We need to set up read config with prefetch to test fallback
119
+ qs = app_models.TestModelSerializerManyToMany.objects.all()
120
+ with mock.patch(
121
+ "django.db.models.query.QuerySet.prefetch_related",
122
+ side_effect=lambda self, *args: self,
123
+ autospec=True,
124
+ ) as m_pref:
125
+ _ = self.query_util_m2m.apply_queryset_optimizations(
126
+ qs, self.query_util_m2m.SCOPES.DETAIL
127
+ )
128
+ # M2M model has no read config, so detail should also have empty prefetch
129
+ m_pref.assert_not_called()
130
+
131
+ def test_detail_config_initialized_with_read_fallback(self):
132
+ """Test that detail_config is initialized with read_config values when not set."""
133
+ # FK model has read config with select_related but no detail config
134
+ self.assertEqual(
135
+ self.query_util_fk.detail_config.select_related,
136
+ self.query_util_fk.read_config.select_related,
137
+ )
138
+ self.assertEqual(
139
+ self.query_util_fk.detail_config.prefetch_related,
140
+ self.query_util_fk.read_config.prefetch_related,
141
+ )
142
+
143
+ def test_detail_config_independent_copy(self):
144
+ """Test that detail_config is a copy, not a reference to read_config lists."""
145
+ # Ensure modifying detail_config doesn't affect read_config
146
+ original_read_select = self.query_util_fk.read_config.select_related.copy()
147
+ self.query_util_fk.detail_config.select_related.append("test_field")
148
+ self.assertEqual(
149
+ self.query_util_fk.read_config.select_related, original_read_select
150
+ )
151
+
152
+
99
153
  @tag("scope_namespace")
100
154
  class ScopeNamespaceTestCase(TestCase):
101
155
  """Tests for ScopeNamespace class (covers line 17 - __iter__)."""