djresttoolkit 1.1.0__tar.gz → 1.2.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.
Files changed (249) hide show
  1. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/PKG-INFO +30 -5
  2. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/README.md +29 -4
  3. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/models.py +20 -1
  4. djresttoolkit-1.2.1/demo/apps/todos/serializers.py +9 -0
  5. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/urls.py +2 -1
  6. djresttoolkit-1.2.1/demo/apps/todos/views.py +43 -0
  7. djresttoolkit-1.2.1/demo/apps_config/__init__.py +3 -0
  8. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/settings.py +3 -1
  9. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/pyproject.toml +13 -9
  10. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/pagination/_paginated_data_builder.py +10 -4
  11. djresttoolkit-1.2.1/src/djresttoolkit/serializers/__init__.py +3 -0
  12. djresttoolkit-1.2.1/src/djresttoolkit/serializers/_enhanced_model_serializer.py +59 -0
  13. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/uv.lock +1 -1
  14. djresttoolkit-1.1.0/demo/apps/todos/views.py +0 -18
  15. djresttoolkit-1.1.0/src/djresttoolkit/serializers/__init__.py +0 -0
  16. djresttoolkit-1.1.0/src/djresttoolkit/views/_apiviews/__init__.py +0 -0
  17. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/.gitignore +0 -0
  18. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/.python-version +0 -0
  19. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/.vscode/settings.json +0 -0
  20. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/LICENSE +0 -0
  21. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/__init__.py +0 -0
  22. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/admin.py +0 -0
  23. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/apps.py +0 -0
  24. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/dbseed/__init__.py +0 -0
  25. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/dbseed/tag_seed.py +0 -0
  26. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/dbseed/todo_seed.py +0 -0
  27. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/dbseed/todo_tag_seed.py +0 -0
  28. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/migrations/0001_initial.py +0 -0
  29. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/migrations/__init__.py +0 -0
  30. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps/todos/tests.py +0 -0
  31. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/asgi.py +0 -0
  32. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/serializers.py +0 -0
  33. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/urls.py +0 -0
  34. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/views.py +0 -0
  35. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/apps_config/wsgi.py +0 -0
  36. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/manage.py +0 -0
  37. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/autocomplete.css +0 -0
  38. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/base.css +0 -0
  39. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/changelists.css +0 -0
  40. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/dark_mode.css +0 -0
  41. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/dashboard.css +0 -0
  42. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/forms.css +0 -0
  43. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/login.css +0 -0
  44. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/nav_sidebar.css +0 -0
  45. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/responsive.css +0 -0
  46. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/responsive_rtl.css +0 -0
  47. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/rtl.css +0 -0
  48. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/unusable_password_field.css +0 -0
  49. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md +0 -0
  50. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/vendor/select2/select2.css +0 -0
  51. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/vendor/select2/select2.min.css +0 -0
  52. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/css/widgets.css +0 -0
  53. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/LICENSE +0 -0
  54. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/README.txt +0 -0
  55. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/calendar-icons.svg +0 -0
  56. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/gis/move_vertex_off.svg +0 -0
  57. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/gis/move_vertex_on.svg +0 -0
  58. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-addlink.svg +0 -0
  59. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-alert.svg +0 -0
  60. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-calendar.svg +0 -0
  61. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-changelink.svg +0 -0
  62. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-clock.svg +0 -0
  63. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-deletelink.svg +0 -0
  64. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-hidelink.svg +0 -0
  65. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-no.svg +0 -0
  66. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-unknown-alt.svg +0 -0
  67. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-unknown.svg +0 -0
  68. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-viewlink.svg +0 -0
  69. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/icon-yes.svg +0 -0
  70. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/inline-delete.svg +0 -0
  71. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/search.svg +0 -0
  72. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/selector-icons.svg +0 -0
  73. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/sorting-icons.svg +0 -0
  74. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/tooltag-add.svg +0 -0
  75. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/img/tooltag-arrowright.svg +0 -0
  76. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/SelectBox.js +0 -0
  77. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/SelectFilter2.js +0 -0
  78. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/actions.js +0 -0
  79. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/admin/DateTimeShortcuts.js +0 -0
  80. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/admin/RelatedObjectLookups.js +0 -0
  81. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/autocomplete.js +0 -0
  82. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/calendar.js +0 -0
  83. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/cancel.js +0 -0
  84. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/change_form.js +0 -0
  85. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/core.js +0 -0
  86. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/filters.js +0 -0
  87. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/inlines.js +0 -0
  88. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/jquery.init.js +0 -0
  89. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/nav_sidebar.js +0 -0
  90. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/popup_response.js +0 -0
  91. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/prepopulate.js +0 -0
  92. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/prepopulate_init.js +0 -0
  93. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/theme.js +0 -0
  94. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/unusable_password_field.js +0 -0
  95. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/urlify.js +0 -0
  96. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/jquery/LICENSE.txt +0 -0
  97. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/jquery/jquery.js +0 -0
  98. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/jquery/jquery.min.js +0 -0
  99. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/LICENSE.md +0 -0
  100. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/af.js +0 -0
  101. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ar.js +0 -0
  102. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/az.js +0 -0
  103. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/bg.js +0 -0
  104. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/bn.js +0 -0
  105. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/bs.js +0 -0
  106. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ca.js +0 -0
  107. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/cs.js +0 -0
  108. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/da.js +0 -0
  109. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/de.js +0 -0
  110. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/dsb.js +0 -0
  111. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/el.js +0 -0
  112. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/en.js +0 -0
  113. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/es.js +0 -0
  114. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/et.js +0 -0
  115. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/eu.js +0 -0
  116. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/fa.js +0 -0
  117. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/fi.js +0 -0
  118. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/fr.js +0 -0
  119. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/gl.js +0 -0
  120. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/he.js +0 -0
  121. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/hi.js +0 -0
  122. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/hr.js +0 -0
  123. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/hsb.js +0 -0
  124. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/hu.js +0 -0
  125. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/hy.js +0 -0
  126. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/id.js +0 -0
  127. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/is.js +0 -0
  128. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/it.js +0 -0
  129. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ja.js +0 -0
  130. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ka.js +0 -0
  131. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/km.js +0 -0
  132. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ko.js +0 -0
  133. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/lt.js +0 -0
  134. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/lv.js +0 -0
  135. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/mk.js +0 -0
  136. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ms.js +0 -0
  137. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/nb.js +0 -0
  138. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ne.js +0 -0
  139. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/nl.js +0 -0
  140. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/pl.js +0 -0
  141. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ps.js +0 -0
  142. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/pt-BR.js +0 -0
  143. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/pt.js +0 -0
  144. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ro.js +0 -0
  145. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/ru.js +0 -0
  146. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sk.js +0 -0
  147. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sl.js +0 -0
  148. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sq.js +0 -0
  149. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sr-Cyrl.js +0 -0
  150. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sr.js +0 -0
  151. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/sv.js +0 -0
  152. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/th.js +0 -0
  153. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/tk.js +0 -0
  154. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/tr.js +0 -0
  155. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/uk.js +0 -0
  156. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/vi.js +0 -0
  157. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/zh-CN.js +0 -0
  158. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/i18n/zh-TW.js +0 -0
  159. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/select2.full.js +0 -0
  160. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/select2/select2.full.min.js +0 -0
  161. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/xregexp/LICENSE.txt +0 -0
  162. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/xregexp/xregexp.js +0 -0
  163. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/admin/js/vendor/xregexp/xregexp.min.js +0 -0
  164. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/bootstrap-theme.min.css +0 -0
  165. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/bootstrap-theme.min.css.map +0 -0
  166. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/bootstrap-tweaks.css +0 -0
  167. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/bootstrap.min.css +0 -0
  168. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/bootstrap.min.css.map +0 -0
  169. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/default.css +0 -0
  170. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/font-awesome-4.0.3.css +0 -0
  171. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/css/prettify.css +0 -0
  172. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/css/base.css +0 -0
  173. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/css/highlight.css +0 -0
  174. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/css/jquery.json-view.min.css +0 -0
  175. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/img/favicon.ico +0 -0
  176. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/img/grid.png +0 -0
  177. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/js/api.js +0 -0
  178. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/js/highlight.pack.js +0 -0
  179. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/docs/js/jquery.json-view.min.js +0 -0
  180. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.eot +0 -0
  181. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.svg +0 -0
  182. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.ttf +0 -0
  183. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.woff +0 -0
  184. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.eot +0 -0
  185. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.svg +0 -0
  186. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.ttf +0 -0
  187. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff +0 -0
  188. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff2 +0 -0
  189. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/img/glyphicons-halflings-white.png +0 -0
  190. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/img/glyphicons-halflings.png +0 -0
  191. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/img/grid.png +0 -0
  192. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/ajax-form.js +0 -0
  193. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/bootstrap.min.js +0 -0
  194. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/coreapi-0.1.1.js +0 -0
  195. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/csrf.js +0 -0
  196. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/default.js +0 -0
  197. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/jquery-3.7.1.min.js +0 -0
  198. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/load-ajax-form.js +0 -0
  199. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/demo/staticfiles/rest_framework/js/prettify-min.js +0 -0
  200. {djresttoolkit-1.1.0/demo/apps_config → djresttoolkit-1.2.1/src/djresttoolkit}/__init__.py +0 -0
  201. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/admin.py +0 -0
  202. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/apps.py +0 -0
  203. {djresttoolkit-1.1.0/src/djresttoolkit → djresttoolkit-1.2.1/src/djresttoolkit/cache}/__init__.py +0 -0
  204. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/__init__.py +0 -0
  205. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/_cache_action_mixin.py +0 -0
  206. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/_cache_invalidate_mixin.py +0 -0
  207. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/_cache_key_mixin.py +0 -0
  208. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/_cache_list_retrieve_mixin.py +0 -0
  209. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/cache/mixins/_cache_ops_mixin.py +0 -0
  210. {djresttoolkit-1.1.0/src/djresttoolkit/cache → djresttoolkit-1.2.1/src/djresttoolkit/dbseed}/__init__.py +0 -0
  211. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/dbseed/models/__init__.py +0 -0
  212. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/dbseed/models/_choice_field.py +0 -0
  213. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/dbseed/models/_gen.py +0 -0
  214. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/dbseed/models/_seed_model.py +0 -0
  215. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/envconfig/__init__.py +0 -0
  216. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/envconfig/_base_env_config.py +0 -0
  217. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/mail/__init__.py +0 -0
  218. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/mail/_email_sender.py +0 -0
  219. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/mail/_models.py +0 -0
  220. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/mail/_types.py +0 -0
  221. {djresttoolkit-1.1.0/src/djresttoolkit/dbseed → djresttoolkit-1.2.1/src/djresttoolkit/management}/__init__.py +0 -0
  222. {djresttoolkit-1.1.0/src/djresttoolkit/management → djresttoolkit-1.2.1/src/djresttoolkit/management/commands}/__init__.py +0 -0
  223. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/management/commands/dbflush.py +0 -0
  224. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/management/commands/dbseed.py +0 -0
  225. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/middlewares/__init__.py +0 -0
  226. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/middlewares/_response_time_middleware.py +0 -0
  227. {djresttoolkit-1.1.0/src/djresttoolkit/management/commands → djresttoolkit-1.2.1/src/djresttoolkit/migrations}/__init__.py +0 -0
  228. {djresttoolkit-1.1.0/src/djresttoolkit/migrations → djresttoolkit-1.2.1/src/djresttoolkit/models}/__init__.py +0 -0
  229. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/models/mixins/__init__.py +0 -0
  230. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/models/mixins/_model_choice_fields_mixin.py +0 -0
  231. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/pagination/__init__.py +0 -0
  232. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/pagination/_page_number_pagination.py +0 -0
  233. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/py.typed +0 -0
  234. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/renderers/__init__.py +0 -0
  235. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/renderers/_throttle_info_json_renderer.py +0 -0
  236. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/serializers/mixins/__init__.py +0 -0
  237. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/serializers/mixins/_absolute_url_file_mixin.py +0 -0
  238. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/serializers/mixins/_bulk_create_mixin.py +0 -0
  239. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/throttling/__init__.py +0 -0
  240. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/throttling/_throttle_inspector.py +0 -0
  241. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/urls/__init__.py +0 -0
  242. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/urls/_build_absolute_uri.py +0 -0
  243. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/__init__.py +0 -0
  244. {djresttoolkit-1.1.0/src/djresttoolkit/models → djresttoolkit-1.2.1/src/djresttoolkit/views/_apiviews}/__init__.py +0 -0
  245. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/_apiviews/_choice_fields_apiview.py +0 -0
  246. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/_exceptions/__init__.py +0 -0
  247. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/_exceptions/_exception_handler.py +0 -0
  248. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/mixins/__init__.py +0 -0
  249. {djresttoolkit-1.1.0 → djresttoolkit-1.2.1}/src/djresttoolkit/views/mixins/_retrieve_object_mixin.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: djresttoolkit
3
- Version: 1.1.0
3
+ Version: 1.2.1
4
4
  Summary: A collection of Django and DRF utilities to simplify API development.
5
5
  Project-URL: Homepage, https://github.com/shaileshpandit141/djresttoolkit
6
6
  Project-URL: Documentation, https://shaileshpandit141.github.io/djresttoolkit
@@ -970,7 +970,7 @@ from djresttoolkit.pagination import PaginatedDataBuilder
970
970
  ```python
971
971
  builder = PaginatedDataBuilder(
972
972
  request=request,
973
- serializer_class=MySerializer,
973
+ serializer_class=BookSerializer,
974
974
  queryset=MyModel.objects.all()
975
975
  )
976
976
  ```
@@ -979,7 +979,7 @@ builder = PaginatedDataBuilder(
979
979
  - `serializer_class: type[BaseSerializer]`:- DRF serializer class for the model.
980
980
  - `queryset: QuerySet`:- Django queryset to paginate.
981
981
 
982
- ### Paginated Data Builder Methods
982
+ ### Paginated Data Builder Methods and Property
983
983
 
984
984
  - `get_paginated_data() -> dict[str, Any]`
985
985
 
@@ -987,6 +987,10 @@ builder = PaginatedDataBuilder(
987
987
  - Serializes the paginated results.
988
988
  - Returns a dictionary with `"page"` and `"results"`.
989
989
  - Raises `NotFound` if no page data is found.
990
+
991
+ - `paginated_data -> dict[str, Any]`
992
+
993
+ - Call `paginated_data` property that internaly call `get_paginated_data()` method
990
994
 
991
995
  ### Example Response of Paginated Data Builder
992
996
 
@@ -1001,8 +1005,8 @@ builder = PaginatedDataBuilder(
1001
1005
  "previous": "http://api.example.com/items/?page=1&page-size=20"
1002
1006
  },
1003
1007
  "results": [
1004
- { "id": 21, "name": "Item 21" },
1005
- { "id": 22, "name": "Item 22" }
1008
+ { "id": 21, "title": "Title 21" },
1009
+ { "id": 22, "title": "Title 22" }
1006
1010
  ]
1007
1011
  }
1008
1012
  ```
@@ -1081,6 +1085,27 @@ class BookViewSet(CacheInvalidateMixin, ModelViewSet):
1081
1085
  - Invalidates caches when books are created, updated, or deleted.
1082
1086
  - Supports custom cache keys per action.
1083
1087
 
1088
+ ### 17. EnhancedModelSerializer — API Reference
1089
+
1090
+ A subclass of Django REST Framework’s `ModelSerializer` that automatically merges Django model field `error_messages` into the serializer field, unless explicitly overridden.
1091
+ This helps maintain consistent validation messages between the model and the serializer.
1092
+
1093
+ #### Type Parameters
1094
+
1095
+ - `T` (`Model`): The Django model type that the serializer corresponds to.
1096
+
1097
+ #### Example of EnhancedModelSerializer
1098
+
1099
+ ```python
1100
+ from myapp.models import Book
1101
+ from myapp.serializers import EnhancedModelSerializer
1102
+
1103
+ class BookSerializer(EnhancedModelSerializer[Book]):
1104
+ class Meta:
1105
+ model = Book
1106
+ fields = "__all__"
1107
+ ```
1108
+
1084
1109
  ## 🛠️ Planned Features
1085
1110
 
1086
1111
  - Add more utils
@@ -914,7 +914,7 @@ from djresttoolkit.pagination import PaginatedDataBuilder
914
914
  ```python
915
915
  builder = PaginatedDataBuilder(
916
916
  request=request,
917
- serializer_class=MySerializer,
917
+ serializer_class=BookSerializer,
918
918
  queryset=MyModel.objects.all()
919
919
  )
920
920
  ```
@@ -923,7 +923,7 @@ builder = PaginatedDataBuilder(
923
923
  - `serializer_class: type[BaseSerializer]`:- DRF serializer class for the model.
924
924
  - `queryset: QuerySet`:- Django queryset to paginate.
925
925
 
926
- ### Paginated Data Builder Methods
926
+ ### Paginated Data Builder Methods and Property
927
927
 
928
928
  - `get_paginated_data() -> dict[str, Any]`
929
929
 
@@ -931,6 +931,10 @@ builder = PaginatedDataBuilder(
931
931
  - Serializes the paginated results.
932
932
  - Returns a dictionary with `"page"` and `"results"`.
933
933
  - Raises `NotFound` if no page data is found.
934
+
935
+ - `paginated_data -> dict[str, Any]`
936
+
937
+ - Call `paginated_data` property that internaly call `get_paginated_data()` method
934
938
 
935
939
  ### Example Response of Paginated Data Builder
936
940
 
@@ -945,8 +949,8 @@ builder = PaginatedDataBuilder(
945
949
  "previous": "http://api.example.com/items/?page=1&page-size=20"
946
950
  },
947
951
  "results": [
948
- { "id": 21, "name": "Item 21" },
949
- { "id": 22, "name": "Item 22" }
952
+ { "id": 21, "title": "Title 21" },
953
+ { "id": 22, "title": "Title 22" }
950
954
  ]
951
955
  }
952
956
  ```
@@ -1025,6 +1029,27 @@ class BookViewSet(CacheInvalidateMixin, ModelViewSet):
1025
1029
  - Invalidates caches when books are created, updated, or deleted.
1026
1030
  - Supports custom cache keys per action.
1027
1031
 
1032
+ ### 17. EnhancedModelSerializer — API Reference
1033
+
1034
+ A subclass of Django REST Framework’s `ModelSerializer` that automatically merges Django model field `error_messages` into the serializer field, unless explicitly overridden.
1035
+ This helps maintain consistent validation messages between the model and the serializer.
1036
+
1037
+ #### Type Parameters
1038
+
1039
+ - `T` (`Model`): The Django model type that the serializer corresponds to.
1040
+
1041
+ #### Example of EnhancedModelSerializer
1042
+
1043
+ ```python
1044
+ from myapp.models import Book
1045
+ from myapp.serializers import EnhancedModelSerializer
1046
+
1047
+ class BookSerializer(EnhancedModelSerializer[Book]):
1048
+ class Meta:
1049
+ model = Book
1050
+ fields = "__all__"
1051
+ ```
1052
+
1028
1053
  ## 🛠️ Planned Features
1029
1054
 
1030
1055
  - Add more utils
@@ -57,8 +57,18 @@ class Todo(BaseModel):
57
57
  on_delete=CASCADE,
58
58
  related_name="todos",
59
59
  help_text="Owner of this todo",
60
+ error_messages={
61
+ "null": "Every todo must belong to a user.",
62
+ "invalid": "Invalid user reference.",
63
+ },
64
+ )
65
+ title: CharField[str, str] = CharField(
66
+ max_length=255,
67
+ error_messages={
68
+ "blank": "Please give your todo a title.",
69
+ "max_length": "The title cannot exceed 255 characters.",
70
+ },
60
71
  )
61
- title: CharField[str, str] = CharField(max_length=255)
62
72
  description: TextField[str, str] = TextField(blank=True, default="")
63
73
  due_date: DateTimeField[str | None, str | None] = DateTimeField(
64
74
  null=True,
@@ -69,16 +79,25 @@ class Todo(BaseModel):
69
79
  max_length=20,
70
80
  choices=TodoPriority.choices,
71
81
  default=TodoPriority.MEDIUM,
82
+ error_messages={
83
+ "invalid_choice": "Priority must be one of: low, medium, high, critical.",
84
+ },
72
85
  )
73
86
  status: CharField[str, str] = CharField(
74
87
  max_length=20,
75
88
  choices=TodoStatus.choices,
76
89
  default=TodoStatus.PENDING,
90
+ error_messages={
91
+ "invalid_choice": "Status must be one of: pending, in_progress, completed, archived.",
92
+ },
77
93
  )
78
94
 
79
95
  completed_at: DateTimeField[str | None, str | None] = DateTimeField(
80
96
  null=True,
81
97
  blank=True,
98
+ error_messages={
99
+ "invalid": "Completed at must be a valid datetime.",
100
+ },
82
101
  )
83
102
 
84
103
  def mark_completed(self) -> None:
@@ -0,0 +1,9 @@
1
+ from djresttoolkit.serializers import EnhancedModelSerializer
2
+
3
+ from .models import Todo
4
+
5
+
6
+ class TodoSerializer(EnhancedModelSerializer[Todo]):
7
+ class Meta:
8
+ model = Todo
9
+ exclude = ["created_at", "updated_at"]
@@ -4,8 +4,9 @@ URL configuration for todos app.
4
4
 
5
5
  from django.urls import path
6
6
 
7
- from .views import TodoDetailView
7
+ from .views import TodoDetailView, TodoListView
8
8
 
9
9
  urlpatterns = [
10
+ path("", TodoListView.as_view(), name="todo-list"),
10
11
  path("<int:id>/", TodoDetailView.as_view(), name="todo-detail"),
11
12
  ]
@@ -0,0 +1,43 @@
1
+ from rest_framework.permissions import AllowAny
2
+ from rest_framework.request import Request
3
+ from rest_framework.response import Response
4
+ from rest_framework.views import APIView
5
+
6
+ from djresttoolkit.pagination import PaginatedDataBuilder
7
+ from djresttoolkit.views.mixins import RetrieveObjectMixin
8
+
9
+ from .models import Todo
10
+ from .serializers import TodoSerializer
11
+
12
+
13
+ class TodoListView(APIView):
14
+ permission_classes = [AllowAny]
15
+
16
+ def get(self, request: Request) -> Response:
17
+ pagination = PaginatedDataBuilder[Todo](
18
+ request=request,
19
+ serializer_class=TodoSerializer,
20
+ queryset=Todo.objects.all(),
21
+ )
22
+ return Response(data=pagination.paginated_data)
23
+
24
+ def post(self, request: Request) -> Response:
25
+ serializer = TodoSerializer(
26
+ data=request.data,
27
+ many=isinstance(request.data, list),
28
+ )
29
+
30
+ if serializer.is_valid():
31
+ serializer.save(user=request.user)
32
+
33
+ return Response(data=serializer.data)
34
+
35
+
36
+ class TodoDetailView(RetrieveObjectMixin[Todo], APIView):
37
+ permission_classes = [AllowAny]
38
+ queryset = Todo.objects.all()
39
+
40
+ def get(self, request: Request, id: int) -> Response:
41
+ todo = self.get_object(id=id)
42
+ serializer = TodoSerializer(instance=todo, many=False)
43
+ return Response(data=serializer.data)
@@ -0,0 +1,3 @@
1
+ from dotenv import load_dotenv
2
+
3
+ load_dotenv()
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ from os import getenv
2
3
  from pathlib import Path
3
4
 
4
5
  # Configuration Settings File for the django backend
@@ -12,7 +13,7 @@ sys.path.insert(0, str(SRC_DIR))
12
13
 
13
14
  # Security Configuration Settings
14
15
  # -------------------------------
15
- SECRET_KEY = "asdkjasdjgasdgjioarejalk54884a651asdgklnaskdg"
16
+ SECRET_KEY = getenv("SECRET_KEY")
16
17
 
17
18
  # DEBUG Configuration Settings
18
19
  # ----------------------------
@@ -164,6 +165,7 @@ MEDIA_URL = "/media/"
164
165
  # -------------------------------------
165
166
  REST_FRAMEWORK = {
166
167
  "NON_FIELD_ERRORS_KEY": "non_field",
168
+ "DATETIME_FORMAT": "%Y-%m-%d %H:%M",
167
169
  "DEFAULT_AUTHENTICATION_CLASSES": [
168
170
  "rest_framework.authentication.TokenAuthentication",
169
171
  ],
@@ -4,7 +4,7 @@
4
4
 
5
5
  [project]
6
6
  name = "djresttoolkit"
7
- version = "1.1.0"
7
+ version = "1.2.1"
8
8
  description = "A collection of Django and DRF utilities to simplify API development."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = { file = "LICENSE" }
@@ -45,10 +45,7 @@ keywords = [
45
45
  "python-package",
46
46
  ]
47
47
  requires-python = ">=3.13"
48
- dependencies = [
49
- "faker>=37.5.3",
50
- "pydantic>=2.11.7",
51
- ]
48
+ dependencies = ["faker>=37.5.3", "pydantic>=2.11.7"]
52
49
 
53
50
  # CLI scripts entry point configuration
54
51
  # -------------------------------------
@@ -109,12 +106,19 @@ Source = "https://github.com/shaileshpandit141/djresttoolkit"
109
106
  Issues = "https://github.com/shaileshpandit141/djresttoolkit/issues"
110
107
  License = "https://github.com/shaileshpandit141/djresttoolkit/blob/main/LICENSE"
111
108
 
112
- # ===================
113
- # Tool Configurations
114
- # ===================
115
109
 
110
+ # ==========================
111
+ # Add pyright Configurations
112
+ # ==========================
113
+ [tool.pyright]
114
+ typeCheckingMode = "strict"
115
+ reportMissingTypeStubs = false
116
+ reportUnknownMemberType = false
117
+ reportIncompatibleVariableOverride = false
118
+
119
+ # =========================================
116
120
  # Disable ruff S101 rule for test casecases
117
- # -----------------------------------------
121
+ # =========================================
118
122
  [tool.ruff.lint.per-file-ignores]
119
123
  "tests/*.py" = ["S101"]
120
124
 
@@ -1,11 +1,13 @@
1
1
  import logging
2
2
  from typing import Any
3
3
 
4
- from django.db.models import QuerySet
4
+ from django.db.models import Model, QuerySet
5
5
  from rest_framework.exceptions import NotFound
6
6
  from rest_framework.request import Request
7
7
  from rest_framework.serializers import BaseSerializer
8
- from django.db.models import Model
8
+
9
+ from djresttoolkit.serializers import EnhancedModelSerializer
10
+
9
11
  from ._page_number_pagination import PageNumberPagination
10
12
 
11
13
  # Get logger from logging.
@@ -18,7 +20,7 @@ class PaginatedDataBuilder[T: Model]:
18
20
  def __init__(
19
21
  self,
20
22
  request: Request,
21
- serializer_class: type[BaseSerializer[T]],
23
+ serializer_class: type[BaseSerializer[T] | EnhancedModelSerializer[T]],
22
24
  queryset: QuerySet[T],
23
25
  ) -> None:
24
26
  """Initilize the PaginatedDataBuilder class."""
@@ -49,7 +51,7 @@ class PaginatedDataBuilder[T: Model]:
49
51
  )
50
52
 
51
53
  # Construct the paginated response
52
- paginated_data = {
54
+ paginated_data: dict[str, Any] = {
53
55
  "page": {
54
56
  "current": paginator.page.number, # type: ignore
55
57
  "total": paginator.page.paginator.num_pages, # type: ignore
@@ -63,3 +65,7 @@ class PaginatedDataBuilder[T: Model]:
63
65
 
64
66
  logger.debug(f"Pagination result: {paginated_data}")
65
67
  return paginated_data
68
+
69
+ @property
70
+ def paginated_data(self) -> dict[str, Any]:
71
+ return self.get_paginated_data()
@@ -0,0 +1,3 @@
1
+ from ._enhanced_model_serializer import EnhancedModelSerializer
2
+
3
+ __all__ = ["EnhancedModelSerializer"]
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+
3
+ from copy import deepcopy
4
+ from typing import Any
5
+
6
+ from django.db.models import Field as DjangoField
7
+ from django.db.models import Model
8
+ from rest_framework.serializers import Field as DrfField
9
+ from rest_framework.serializers import ModelSerializer
10
+ from rest_framework.utils.model_meta import RelationInfo
11
+
12
+
13
+ class EnhancedModelSerializer[T: Model](ModelSerializer[Model]):
14
+ """
15
+ A DRF ModelSerializer that automatically applies Django model field
16
+ `error_messages` unless explicitly overridden in the serializer.
17
+ """
18
+
19
+ def _merge_error_messages(
20
+ self,
21
+ field_kwargs: dict[str, Any],
22
+ model_field: DjangoField[Any, Any] | None,
23
+ ) -> dict[str, Any]:
24
+ """Safely merge model field error_messages with serializer kwargs."""
25
+ model_errors: dict[str, str] | None = getattr(
26
+ model_field, "error_messages", None
27
+ )
28
+ if model_errors:
29
+ existing: dict[str, str] = field_kwargs.get("error_messages", {})
30
+ field_kwargs["error_messages"] = {**deepcopy(model_errors), **existing}
31
+ return field_kwargs
32
+
33
+ def build_standard_field(
34
+ self,
35
+ field_name: str,
36
+ model_field: DjangoField[Any, Any],
37
+ ) -> tuple[type[DrfField[Any, Any, Any, Any]], dict[str, Any]]:
38
+ field_class, field_kwargs = super().build_standard_field( # type: ignore
39
+ field_name,
40
+ model_field,
41
+ )
42
+ return field_class, self._merge_error_messages(
43
+ field_kwargs,
44
+ model_field,
45
+ ) # type: ignore
46
+
47
+ def build_relational_field(
48
+ self,
49
+ field_name: str,
50
+ relation_info: RelationInfo,
51
+ ) -> tuple[type[DrfField[Any, Any, Any, Any]], dict[str, Any]]:
52
+ field_class, field_kwargs = super().build_relational_field( # type: ignore
53
+ field_name,
54
+ relation_info,
55
+ )
56
+ return field_class, self._merge_error_messages(
57
+ field_kwargs,
58
+ relation_info.model_field, # type: ignore
59
+ )
@@ -342,7 +342,7 @@ wheels = [
342
342
 
343
343
  [[package]]
344
344
  name = "djresttoolkit"
345
- version = "1.0.0"
345
+ version = "1.1.0"
346
346
  source = { editable = "." }
347
347
  dependencies = [
348
348
  { name = "faker" },
@@ -1,18 +0,0 @@
1
- from django.forms.models import model_to_dict
2
- from rest_framework.permissions import AllowAny
3
- from rest_framework.request import Request
4
- from rest_framework.response import Response
5
- from rest_framework.views import APIView
6
-
7
- from djresttoolkit.views.mixins import RetrieveObjectMixin
8
-
9
- from .models import Todo
10
-
11
-
12
- class TodoDetailView(RetrieveObjectMixin[Todo], APIView):
13
- permission_classes = [AllowAny]
14
- queryset = Todo.objects.all()
15
-
16
- def get(self, request: Request, id: int) -> Response:
17
- todo = self.get_object(id=id)
18
- return Response(data=model_to_dict(todo))
File without changes
File without changes