djresttoolkit 0.17.5__tar.gz → 1.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 (252) hide show
  1. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/PKG-INFO +41 -68
  2. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/README.md +40 -65
  3. djresttoolkit-1.1.0/demo/apps/todos/urls.py +11 -0
  4. djresttoolkit-1.1.0/demo/apps/todos/views.py +18 -0
  5. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/settings.py +4 -22
  6. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/pyproject.toml +1 -3
  7. djresttoolkit-1.1.0/src/djresttoolkit/envconfig/__init__.py +4 -0
  8. djresttoolkit-1.1.0/src/djresttoolkit/envconfig/_base_env_config.py +84 -0
  9. djresttoolkit-1.1.0/src/djresttoolkit/views/mixins/__init__.py +3 -0
  10. djresttoolkit-1.1.0/src/djresttoolkit/views/mixins/_retrieve_object_mixin.py +59 -0
  11. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/uv.lock +1 -5
  12. djresttoolkit-0.17.5/demo/apps/todos/urls.py +0 -7
  13. djresttoolkit-0.17.5/demo/apps/todos/views.py +0 -0
  14. djresttoolkit-0.17.5/demo/env_config/__init__.py +0 -3
  15. djresttoolkit-0.17.5/demo/env_config/env_settings.py +0 -54
  16. djresttoolkit-0.17.5/src/djresttoolkit/envconfig/__init__.py +0 -3
  17. djresttoolkit-0.17.5/src/djresttoolkit/envconfig/_env_settings.py +0 -84
  18. djresttoolkit-0.17.5/src/djresttoolkit/views/mixins/__init__.py +0 -6
  19. djresttoolkit-0.17.5/src/djresttoolkit/views/mixins/_retrieve_object_mixin.py +0 -41
  20. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/.gitignore +0 -0
  21. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/.python-version +0 -0
  22. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/.vscode/settings.json +0 -0
  23. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/LICENSE +0 -0
  24. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/__init__.py +0 -0
  25. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/admin.py +0 -0
  26. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/apps.py +0 -0
  27. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/dbseed/__init__.py +0 -0
  28. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/dbseed/tag_seed.py +0 -0
  29. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/dbseed/todo_seed.py +0 -0
  30. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/dbseed/todo_tag_seed.py +0 -0
  31. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/migrations/0001_initial.py +0 -0
  32. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/migrations/__init__.py +0 -0
  33. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/models.py +0 -0
  34. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps/todos/tests.py +0 -0
  35. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/__init__.py +0 -0
  36. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/asgi.py +0 -0
  37. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/serializers.py +0 -0
  38. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/urls.py +0 -0
  39. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/views.py +0 -0
  40. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/apps_config/wsgi.py +0 -0
  41. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/manage.py +0 -0
  42. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/autocomplete.css +0 -0
  43. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/base.css +0 -0
  44. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/changelists.css +0 -0
  45. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/dark_mode.css +0 -0
  46. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/dashboard.css +0 -0
  47. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/forms.css +0 -0
  48. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/login.css +0 -0
  49. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/nav_sidebar.css +0 -0
  50. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/responsive.css +0 -0
  51. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/responsive_rtl.css +0 -0
  52. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/rtl.css +0 -0
  53. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/unusable_password_field.css +0 -0
  54. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md +0 -0
  55. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/vendor/select2/select2.css +0 -0
  56. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/vendor/select2/select2.min.css +0 -0
  57. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/css/widgets.css +0 -0
  58. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/LICENSE +0 -0
  59. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/README.txt +0 -0
  60. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/calendar-icons.svg +0 -0
  61. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/gis/move_vertex_off.svg +0 -0
  62. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/gis/move_vertex_on.svg +0 -0
  63. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-addlink.svg +0 -0
  64. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-alert.svg +0 -0
  65. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-calendar.svg +0 -0
  66. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-changelink.svg +0 -0
  67. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-clock.svg +0 -0
  68. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-deletelink.svg +0 -0
  69. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-hidelink.svg +0 -0
  70. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-no.svg +0 -0
  71. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-unknown-alt.svg +0 -0
  72. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-unknown.svg +0 -0
  73. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-viewlink.svg +0 -0
  74. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/icon-yes.svg +0 -0
  75. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/inline-delete.svg +0 -0
  76. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/search.svg +0 -0
  77. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/selector-icons.svg +0 -0
  78. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/sorting-icons.svg +0 -0
  79. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/tooltag-add.svg +0 -0
  80. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/img/tooltag-arrowright.svg +0 -0
  81. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/SelectBox.js +0 -0
  82. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/SelectFilter2.js +0 -0
  83. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/actions.js +0 -0
  84. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/admin/DateTimeShortcuts.js +0 -0
  85. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/admin/RelatedObjectLookups.js +0 -0
  86. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/autocomplete.js +0 -0
  87. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/calendar.js +0 -0
  88. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/cancel.js +0 -0
  89. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/change_form.js +0 -0
  90. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/core.js +0 -0
  91. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/filters.js +0 -0
  92. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/inlines.js +0 -0
  93. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/jquery.init.js +0 -0
  94. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/nav_sidebar.js +0 -0
  95. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/popup_response.js +0 -0
  96. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/prepopulate.js +0 -0
  97. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/prepopulate_init.js +0 -0
  98. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/theme.js +0 -0
  99. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/unusable_password_field.js +0 -0
  100. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/urlify.js +0 -0
  101. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/jquery/LICENSE.txt +0 -0
  102. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/jquery/jquery.js +0 -0
  103. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/jquery/jquery.min.js +0 -0
  104. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/LICENSE.md +0 -0
  105. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/af.js +0 -0
  106. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ar.js +0 -0
  107. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/az.js +0 -0
  108. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/bg.js +0 -0
  109. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/bn.js +0 -0
  110. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/bs.js +0 -0
  111. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ca.js +0 -0
  112. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/cs.js +0 -0
  113. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/da.js +0 -0
  114. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/de.js +0 -0
  115. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/dsb.js +0 -0
  116. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/el.js +0 -0
  117. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/en.js +0 -0
  118. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/es.js +0 -0
  119. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/et.js +0 -0
  120. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/eu.js +0 -0
  121. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/fa.js +0 -0
  122. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/fi.js +0 -0
  123. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/fr.js +0 -0
  124. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/gl.js +0 -0
  125. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/he.js +0 -0
  126. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/hi.js +0 -0
  127. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/hr.js +0 -0
  128. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/hsb.js +0 -0
  129. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/hu.js +0 -0
  130. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/hy.js +0 -0
  131. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/id.js +0 -0
  132. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/is.js +0 -0
  133. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/it.js +0 -0
  134. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ja.js +0 -0
  135. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ka.js +0 -0
  136. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/km.js +0 -0
  137. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ko.js +0 -0
  138. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/lt.js +0 -0
  139. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/lv.js +0 -0
  140. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/mk.js +0 -0
  141. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ms.js +0 -0
  142. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/nb.js +0 -0
  143. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ne.js +0 -0
  144. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/nl.js +0 -0
  145. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/pl.js +0 -0
  146. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ps.js +0 -0
  147. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/pt-BR.js +0 -0
  148. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/pt.js +0 -0
  149. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ro.js +0 -0
  150. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/ru.js +0 -0
  151. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sk.js +0 -0
  152. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sl.js +0 -0
  153. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sq.js +0 -0
  154. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sr-Cyrl.js +0 -0
  155. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sr.js +0 -0
  156. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/sv.js +0 -0
  157. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/th.js +0 -0
  158. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/tk.js +0 -0
  159. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/tr.js +0 -0
  160. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/uk.js +0 -0
  161. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/vi.js +0 -0
  162. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/zh-CN.js +0 -0
  163. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/i18n/zh-TW.js +0 -0
  164. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/select2.full.js +0 -0
  165. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/select2/select2.full.min.js +0 -0
  166. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/xregexp/LICENSE.txt +0 -0
  167. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/xregexp/xregexp.js +0 -0
  168. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/admin/js/vendor/xregexp/xregexp.min.js +0 -0
  169. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/bootstrap-theme.min.css +0 -0
  170. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/bootstrap-theme.min.css.map +0 -0
  171. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/bootstrap-tweaks.css +0 -0
  172. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/bootstrap.min.css +0 -0
  173. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/bootstrap.min.css.map +0 -0
  174. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/default.css +0 -0
  175. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/font-awesome-4.0.3.css +0 -0
  176. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/css/prettify.css +0 -0
  177. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/css/base.css +0 -0
  178. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/css/highlight.css +0 -0
  179. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/css/jquery.json-view.min.css +0 -0
  180. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/img/favicon.ico +0 -0
  181. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/img/grid.png +0 -0
  182. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/js/api.js +0 -0
  183. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/js/highlight.pack.js +0 -0
  184. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/docs/js/jquery.json-view.min.js +0 -0
  185. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.eot +0 -0
  186. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.svg +0 -0
  187. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.ttf +0 -0
  188. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/fontawesome-webfont.woff +0 -0
  189. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.eot +0 -0
  190. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.svg +0 -0
  191. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.ttf +0 -0
  192. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff +0 -0
  193. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff2 +0 -0
  194. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/img/glyphicons-halflings-white.png +0 -0
  195. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/img/glyphicons-halflings.png +0 -0
  196. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/img/grid.png +0 -0
  197. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/ajax-form.js +0 -0
  198. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/bootstrap.min.js +0 -0
  199. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/coreapi-0.1.1.js +0 -0
  200. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/csrf.js +0 -0
  201. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/default.js +0 -0
  202. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/jquery-3.7.1.min.js +0 -0
  203. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/load-ajax-form.js +0 -0
  204. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/demo/staticfiles/rest_framework/js/prettify-min.js +0 -0
  205. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/__init__.py +0 -0
  206. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/admin.py +0 -0
  207. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/apps.py +0 -0
  208. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/__init__.py +0 -0
  209. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/__init__.py +0 -0
  210. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/_cache_action_mixin.py +0 -0
  211. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/_cache_invalidate_mixin.py +0 -0
  212. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/_cache_key_mixin.py +0 -0
  213. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/_cache_list_retrieve_mixin.py +0 -0
  214. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/cache/mixins/_cache_ops_mixin.py +0 -0
  215. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/dbseed/__init__.py +0 -0
  216. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/dbseed/models/__init__.py +0 -0
  217. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/dbseed/models/_choice_field.py +0 -0
  218. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/dbseed/models/_gen.py +0 -0
  219. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/dbseed/models/_seed_model.py +0 -0
  220. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/mail/__init__.py +0 -0
  221. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/mail/_email_sender.py +0 -0
  222. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/mail/_models.py +0 -0
  223. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/mail/_types.py +0 -0
  224. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/management/__init__.py +0 -0
  225. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/management/commands/__init__.py +0 -0
  226. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/management/commands/dbflush.py +0 -0
  227. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/management/commands/dbseed.py +0 -0
  228. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/middlewares/__init__.py +0 -0
  229. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/middlewares/_response_time_middleware.py +0 -0
  230. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/migrations/__init__.py +0 -0
  231. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/models/__init__.py +0 -0
  232. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/models/mixins/__init__.py +0 -0
  233. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/models/mixins/_model_choice_fields_mixin.py +0 -0
  234. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/pagination/__init__.py +0 -0
  235. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/pagination/_page_number_pagination.py +0 -0
  236. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/pagination/_paginated_data_builder.py +0 -0
  237. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/py.typed +0 -0
  238. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/renderers/__init__.py +0 -0
  239. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/renderers/_throttle_info_json_renderer.py +0 -0
  240. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/serializers/__init__.py +0 -0
  241. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/serializers/mixins/__init__.py +0 -0
  242. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/serializers/mixins/_absolute_url_file_mixin.py +0 -0
  243. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/serializers/mixins/_bulk_create_mixin.py +0 -0
  244. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/throttling/__init__.py +0 -0
  245. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/throttling/_throttle_inspector.py +0 -0
  246. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/urls/__init__.py +0 -0
  247. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/urls/_build_absolute_uri.py +0 -0
  248. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/views/__init__.py +0 -0
  249. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/views/_apiviews/__init__.py +0 -0
  250. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/views/_apiviews/_choice_fields_apiview.py +0 -0
  251. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/views/_exceptions/__init__.py +0 -0
  252. {djresttoolkit-0.17.5 → djresttoolkit-1.1.0}/src/djresttoolkit/views/_exceptions/_exception_handler.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: djresttoolkit
3
- Version: 0.17.5
3
+ Version: 1.1.0
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
@@ -47,9 +47,7 @@ Classifier: Topic :: Utilities
47
47
  Classifier: Typing :: Typed
48
48
  Requires-Python: >=3.13
49
49
  Requires-Dist: faker>=37.5.3
50
- Requires-Dist: pydantic-settings>=2.10.1
51
50
  Requires-Dist: pydantic>=2.11.7
52
- Requires-Dist: pyyaml>=6.0.2
53
51
  Provides-Extra: dev
54
52
  Requires-Dist: mypy; extra == 'dev'
55
53
  Requires-Dist: pytest; extra == 'dev'
@@ -72,8 +70,8 @@ djresttoolkit is a collection of utilities and helpers for Django and Django RES
72
70
  - **DB Flush Command (`dbflush`)**
73
71
  Management command to flush all models or a specific model, resetting auto-increment IDs safely with transaction support.
74
72
 
75
- - **EnvBaseSettings**
76
- Typed settings loader using **YAML + .env**, supports nested keys and overrides. Great for structured configuration management.
73
+ - **BaseEnvConfig**
74
+ Singleton environment loader that reads and parses environment variables.
77
75
 
78
76
  - **EmailSender**
79
77
  Custom class to send templated emails (`text` and `html`) with context. Supports error handling and logging.
@@ -186,10 +184,6 @@ python manage.py dbseed --count 10
186
184
  python manage.py dbseed --model User --seed 42
187
185
  ```
188
186
 
189
- Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
190
-
191
- ---
192
-
193
187
  ### 2. DB Flush Command — API Reference
194
188
 
195
189
  ```python
@@ -246,77 +240,54 @@ or
246
240
  Flushed 120 records from all models and reset IDs.
247
241
  ```
248
242
 
249
- ### 3. EnvBaseSettings — API Reference
243
+ ### 3. BaseEnvConfig — API Reference
250
244
 
251
245
  ```python
252
- from djresttoolkit.envconfig import EnvBaseSettings
246
+ from djresttoolkit.envconfig import BaseEnvConfig
253
247
  ```
254
248
 
255
- #### `EnvBaseSettings`
256
-
257
- A **base settings class** for managing application configuration using:
258
-
259
- - YAML files (default `.environ.yaml`)
260
- - Environment variables (default `.env`)
261
-
262
- Supports **nested configuration** using double underscores (`__`) in environment variable names.
263
-
264
- #### Class Attributes
265
-
266
- - Attributes
267
- - `env_file`
268
- - Type: `str`
269
- - Default: `.env`
270
- - Description: Environment variable file path.
271
- - `yaml_file`
272
- - Type: `str`
273
- - Default: `.environ.yaml`
274
- - Description: YAML configuration file path.
275
- - `model_config`
276
- - Type: `SettingsConfigDict`
277
- - Description: Pydantic settings configuration (file encoding, nested delimiter).
278
-
279
- #### Methods
249
+ #### `BaseEnvConfig`
280
250
 
281
- #### `load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> EnvBaseSettings`
251
+ Singleton environment loader that reads and parses environment variables with support for booleans, numbers, and JSON.
282
252
 
283
- Loads configuration from **YAML first**, then overrides with **environment variables**.
253
+ > ⚠️ **Note:** Note: If you are using a .env file, load it first with python-dotenv:
254
+ >
255
+ > ```python
256
+ > from dotenv import load_dotenv
257
+ > load_dotenv()
258
+ > ```
284
259
 
285
- #### Parameters
286
-
287
- - `env_file` — Optional custom `.env` file path.
288
- - `ymal_file` Optional custom YAML file path.
289
- - `warning` — Emit a warning if YAML file is missing (default `True`).
290
-
291
- #### Returns
292
-
293
- - Instance of `EnvBaseSettings` (or subclass) with loaded configuration.
294
-
295
- #### Raises
296
-
297
- - `UserWarning` if YAML file not found and `warning=True`.
260
+ or
261
+ >
262
+ > ```python
263
+ > from djresttoolkit.envconfig import load_dotenv
264
+ > load_dotenv()
265
+ > ```
298
266
 
299
- ### Usage Example
267
+ #### Usage Example
300
268
 
301
269
  ```python
302
- from djresttoolkit.envconfig import EnvBaseSettings
270
+ from djresttoolkit.envconfig import load_dotenv, BaseEnvConfig
303
271
 
304
- class EnvSettings(EnvBaseSettings["EnvSettings"]):
305
- debug: bool = False
306
- database_url: str
272
+ load_dotenv()
307
273
 
308
- # Load settings
309
- settings = EnvSettings.load(warning=False)
274
+ class EnvConfig(BaseEnvConfig):
275
+ DEBUG: bool = False
276
+ DATABASE_URL: str
310
277
 
311
- print(settings.debug)
312
- print(settings.database_url)
278
+ config = EnvConfig()
279
+ print(config.DEBUG)
280
+ print(config.DATABASE_URL)
281
+
282
+ config.reload()
313
283
  ```
314
284
 
315
285
  #### Features
316
286
 
317
- - Prioritizes `.env` variables over YAML.
318
- - Supports nested keys: `DATABASE__HOST`:- `settings.database.host`.
319
- - Designed to be subclassed for project-specific settings.
287
+ - Thread-safe singleton.
288
+ - Automatic type parsing for environment variables.
289
+ - Supports default values and runtime reloading.
290
+ - Designed for subclassing with project-specific settings.
320
291
 
321
292
  ### 4. EmailSender — API Reference
322
293
 
@@ -830,6 +801,7 @@ Retrieve a single model object using the provided filter criteria.
830
801
 
831
802
  ```python
832
803
  from rest_framework.views import APIView
804
+ from rest_framework.response import Respone
833
805
  from django.http import JsonResponse
834
806
  from myapp.models import Book
835
807
  from djresttoolkit.mixins import RetrieveObjectMixin
@@ -837,17 +809,18 @@ from djresttoolkit.mixins import RetrieveObjectMixin
837
809
  class BookDetailView(RetrieveObjectMixin[Book], APIView):
838
810
  queryset = Book.objects.all()
839
811
 
840
- def get(self, request, *args, **kwargs):
812
+ def not_found_detail(self) -> dict[str, str] | str:
813
+ return "The requested Book was not found."
814
+
815
+ def get(self, request, *args, **kwargs) -> Respone:
841
816
  book = self.get_object(id=kwargs["id"])
842
- if book:
843
- return JsonResponse({"title": book.title, "author": book.author})
844
- return JsonResponse({"detail": "Not found"}, status=404)
817
+ return Respone({"title": book.title, "author": book.author})
845
818
  ```
846
819
 
847
820
  #### Features of Retrieve Object Mixin
848
821
 
849
822
  - Simplifies object retrieval in class-based views or DRF views.
850
- - Returns `None` instead of raising `DoesNotExist`, making error handling easier.
823
+ - Raise `http404` if requested resource does not extst.
851
824
  - Works with any Django model and queryset.
852
825
 
853
826
  ### 13. build_absolute_uri — API Reference
@@ -14,8 +14,8 @@ djresttoolkit is a collection of utilities and helpers for Django and Django RES
14
14
  - **DB Flush Command (`dbflush`)**
15
15
  Management command to flush all models or a specific model, resetting auto-increment IDs safely with transaction support.
16
16
 
17
- - **EnvBaseSettings**
18
- Typed settings loader using **YAML + .env**, supports nested keys and overrides. Great for structured configuration management.
17
+ - **BaseEnvConfig**
18
+ Singleton environment loader that reads and parses environment variables.
19
19
 
20
20
  - **EmailSender**
21
21
  Custom class to send templated emails (`text` and `html`) with context. Supports error handling and logging.
@@ -128,10 +128,6 @@ python manage.py dbseed --count 10
128
128
  python manage.py dbseed --model User --seed 42
129
129
  ```
130
130
 
131
- Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
132
-
133
- ---
134
-
135
131
  ### 2. DB Flush Command — API Reference
136
132
 
137
133
  ```python
@@ -188,77 +184,54 @@ or
188
184
  Flushed 120 records from all models and reset IDs.
189
185
  ```
190
186
 
191
- ### 3. EnvBaseSettings — API Reference
187
+ ### 3. BaseEnvConfig — API Reference
192
188
 
193
189
  ```python
194
- from djresttoolkit.envconfig import EnvBaseSettings
190
+ from djresttoolkit.envconfig import BaseEnvConfig
195
191
  ```
196
192
 
197
- #### `EnvBaseSettings`
198
-
199
- A **base settings class** for managing application configuration using:
200
-
201
- - YAML files (default `.environ.yaml`)
202
- - Environment variables (default `.env`)
203
-
204
- Supports **nested configuration** using double underscores (`__`) in environment variable names.
205
-
206
- #### Class Attributes
207
-
208
- - Attributes
209
- - `env_file`
210
- - Type: `str`
211
- - Default: `.env`
212
- - Description: Environment variable file path.
213
- - `yaml_file`
214
- - Type: `str`
215
- - Default: `.environ.yaml`
216
- - Description: YAML configuration file path.
217
- - `model_config`
218
- - Type: `SettingsConfigDict`
219
- - Description: Pydantic settings configuration (file encoding, nested delimiter).
220
-
221
- #### Methods
193
+ #### `BaseEnvConfig`
222
194
 
223
- #### `load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> EnvBaseSettings`
195
+ Singleton environment loader that reads and parses environment variables with support for booleans, numbers, and JSON.
224
196
 
225
- Loads configuration from **YAML first**, then overrides with **environment variables**.
197
+ > ⚠️ **Note:** Note: If you are using a .env file, load it first with python-dotenv:
198
+ >
199
+ > ```python
200
+ > from dotenv import load_dotenv
201
+ > load_dotenv()
202
+ > ```
226
203
 
227
- #### Parameters
228
-
229
- - `env_file` — Optional custom `.env` file path.
230
- - `ymal_file` Optional custom YAML file path.
231
- - `warning` — Emit a warning if YAML file is missing (default `True`).
232
-
233
- #### Returns
234
-
235
- - Instance of `EnvBaseSettings` (or subclass) with loaded configuration.
236
-
237
- #### Raises
238
-
239
- - `UserWarning` if YAML file not found and `warning=True`.
204
+ or
205
+ >
206
+ > ```python
207
+ > from djresttoolkit.envconfig import load_dotenv
208
+ > load_dotenv()
209
+ > ```
240
210
 
241
- ### Usage Example
211
+ #### Usage Example
242
212
 
243
213
  ```python
244
- from djresttoolkit.envconfig import EnvBaseSettings
214
+ from djresttoolkit.envconfig import load_dotenv, BaseEnvConfig
245
215
 
246
- class EnvSettings(EnvBaseSettings["EnvSettings"]):
247
- debug: bool = False
248
- database_url: str
216
+ load_dotenv()
249
217
 
250
- # Load settings
251
- settings = EnvSettings.load(warning=False)
218
+ class EnvConfig(BaseEnvConfig):
219
+ DEBUG: bool = False
220
+ DATABASE_URL: str
252
221
 
253
- print(settings.debug)
254
- print(settings.database_url)
222
+ config = EnvConfig()
223
+ print(config.DEBUG)
224
+ print(config.DATABASE_URL)
225
+
226
+ config.reload()
255
227
  ```
256
228
 
257
229
  #### Features
258
230
 
259
- - Prioritizes `.env` variables over YAML.
260
- - Supports nested keys: `DATABASE__HOST`:- `settings.database.host`.
261
- - Designed to be subclassed for project-specific settings.
231
+ - Thread-safe singleton.
232
+ - Automatic type parsing for environment variables.
233
+ - Supports default values and runtime reloading.
234
+ - Designed for subclassing with project-specific settings.
262
235
 
263
236
  ### 4. EmailSender — API Reference
264
237
 
@@ -772,6 +745,7 @@ Retrieve a single model object using the provided filter criteria.
772
745
 
773
746
  ```python
774
747
  from rest_framework.views import APIView
748
+ from rest_framework.response import Respone
775
749
  from django.http import JsonResponse
776
750
  from myapp.models import Book
777
751
  from djresttoolkit.mixins import RetrieveObjectMixin
@@ -779,17 +753,18 @@ from djresttoolkit.mixins import RetrieveObjectMixin
779
753
  class BookDetailView(RetrieveObjectMixin[Book], APIView):
780
754
  queryset = Book.objects.all()
781
755
 
782
- def get(self, request, *args, **kwargs):
756
+ def not_found_detail(self) -> dict[str, str] | str:
757
+ return "The requested Book was not found."
758
+
759
+ def get(self, request, *args, **kwargs) -> Respone:
783
760
  book = self.get_object(id=kwargs["id"])
784
- if book:
785
- return JsonResponse({"title": book.title, "author": book.author})
786
- return JsonResponse({"detail": "Not found"}, status=404)
761
+ return Respone({"title": book.title, "author": book.author})
787
762
  ```
788
763
 
789
764
  #### Features of Retrieve Object Mixin
790
765
 
791
766
  - Simplifies object retrieval in class-based views or DRF views.
792
- - Returns `None` instead of raising `DoesNotExist`, making error handling easier.
767
+ - Raise `http404` if requested resource does not extst.
793
768
  - Works with any Django model and queryset.
794
769
 
795
770
  ### 13. build_absolute_uri — API Reference
@@ -0,0 +1,11 @@
1
+ """
2
+ URL configuration for todos app.
3
+ """
4
+
5
+ from django.urls import path
6
+
7
+ from .views import TodoDetailView
8
+
9
+ urlpatterns = [
10
+ path("<int:id>/", TodoDetailView.as_view(), name="todo-detail"),
11
+ ]
@@ -0,0 +1,18 @@
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))
@@ -1,8 +1,6 @@
1
1
  import sys
2
2
  from pathlib import Path
3
3
 
4
- from env_config import env_settings
5
-
6
4
  # Configuration Settings File for the django backend
7
5
  # --------------------------------------------------
8
6
  BASE_DIR = Path(__file__).resolve().parent.parent.parent
@@ -14,7 +12,7 @@ sys.path.insert(0, str(SRC_DIR))
14
12
 
15
13
  # Security Configuration Settings
16
14
  # -------------------------------
17
- SECRET_KEY = env_settings.secret_key
15
+ SECRET_KEY = "asdkjasdjgasdgjioarejalk54884a651asdgklnaskdg"
18
16
 
19
17
  # DEBUG Configuration Settings
20
18
  # ----------------------------
@@ -22,11 +20,11 @@ DEBUG = True
22
20
 
23
21
  # Allowed Host Configuration Settings
24
22
  # -----------------------------------
25
- ALLOWED_HOSTS = env_settings.allowed_hosts
23
+ ALLOWED_HOSTS = ["*"]
26
24
 
27
25
  # Configure CORS Settings
28
26
  # -----------------------
29
- CORS_ALLOWED_ORIGINS = env_settings.cors_allowed_origins
27
+ # CORS_ALLOWED_ORIGINS = []
30
28
 
31
29
  # Login Redirect URL Configuration Setting
32
30
  # ----------------------------------------
@@ -200,29 +198,13 @@ REST_FRAMEWORK = {
200
198
  # -------------------------------------
201
199
  AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.ModelBackend"]
202
200
 
203
- # EMAIL Configuration Settings
204
- # ----------------------------
205
- EMAIL_BACKEND = env_settings.email.backend # type: ignore[]
206
- EMAIL_HOST = env_settings.email.host
207
- EMAIL_PORT = env_settings.email.port
208
- EMAIL_USE_TLS = env_settings.email.use_tls
209
- EMAIL_USE_SSL = env_settings.email.use_ssl
210
- EMAIL_HOST_USER = env_settings.email.host_user
211
- EMAIL_HOST_PASSWORD = env_settings.email.host_password
212
- DEFAULT_FROM_EMAIL = env_settings.email.default_from_email
213
-
214
- # Google OAuth2 Configuration Settings
215
- # ------------------------------------
216
- GOOGLE_CLIENT_ID = env_settings.google.client_id
217
- GOOGLE_CLIENT_SECRET = env_settings.google.client_secret
218
- GOOGLE_REDIRECT_URI = env_settings.google.redirect_url
219
201
 
220
202
  # Redis configuration for production
221
203
  # ----------------------------------
222
204
  CACHES = {
223
205
  "default": {
224
206
  "BACKEND": "django_redis.cache.RedisCache",
225
- "LOCATION": env_settings.redis.cache_location,
207
+ "LOCATION": "redis://localhost:6379/1",
226
208
  "OPTIONS": {
227
209
  "CLIENT_CLASS": "django_redis.client.DefaultClient",
228
210
  },
@@ -4,7 +4,7 @@
4
4
 
5
5
  [project]
6
6
  name = "djresttoolkit"
7
- version = "0.17.5"
7
+ version = "1.1.0"
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" }
@@ -48,8 +48,6 @@ requires-python = ">=3.13"
48
48
  dependencies = [
49
49
  "faker>=37.5.3",
50
50
  "pydantic>=2.11.7",
51
- "pydantic-settings>=2.10.1",
52
- "pyyaml>=6.0.2",
53
51
  ]
54
52
 
55
53
  # CLI scripts entry point configuration
@@ -0,0 +1,4 @@
1
+ from ._base_env_config import BaseEnvConfig
2
+ from dotenv import load_dotenv
3
+
4
+ __all__ = ["load_dotenv", "BaseEnvConfig"]
@@ -0,0 +1,84 @@
1
+ import threading
2
+ import json
3
+ from os import getenv
4
+ from typing import Any, Self, get_type_hints
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ class BaseEnvConfig:
11
+ """Production-ready environment loader."""
12
+
13
+ _instance_lock = threading.Lock()
14
+ _instance = None
15
+
16
+ def __new__(cls, *args: Any, **kwargs: Any) -> Self:
17
+ if cls._instance is None:
18
+ with cls._instance_lock:
19
+ if cls._instance is None:
20
+ cls._instance = super().__new__(cls)
21
+ return cls._instance
22
+
23
+ def __init__(self) -> None:
24
+ if getattr(self, "_initialized", False):
25
+ return
26
+
27
+ self._env_cache: dict[str, Any] = {}
28
+ self._sync_env()
29
+ self._initialized = True
30
+
31
+ def _sync_env(self) -> None:
32
+ hints = get_type_hints(self.__class__)
33
+ for field, _ in hints.items():
34
+ raw = getenv(field)
35
+
36
+ if raw is None:
37
+ if hasattr(self, field):
38
+ value = getattr(self, field)
39
+ logger.info(f"{field} not set, using default: {value}")
40
+ else:
41
+ raise EnvironmentError(
42
+ f"Missing required environment variable: {field}"
43
+ )
44
+ else:
45
+ if field in self._env_cache:
46
+ value = self._env_cache[field]
47
+ else:
48
+ value = self._parse_env_value(raw)
49
+ self._env_cache[field] = value
50
+
51
+ setattr(self, field, value)
52
+
53
+ def _parse_env_value(self, raw: str) -> Any:
54
+ """Parse string from environment."""
55
+ lowered = raw.lower()
56
+
57
+ # Boolean parsing
58
+ if lowered == "true":
59
+ return True
60
+ if lowered == "false":
61
+ return False
62
+
63
+ # JSON parsing
64
+ try:
65
+ return json.loads(raw)
66
+ except json.JSONDecodeError:
67
+ pass
68
+
69
+ # Numeric parsing
70
+ if raw.isdigit():
71
+ return int(raw)
72
+ try:
73
+ return float(raw)
74
+ except ValueError:
75
+ pass
76
+
77
+ # Fallback: plain string
78
+ return raw
79
+
80
+ def reload(self) -> None:
81
+ """Reload environment variables at runtime."""
82
+ self._env_cache.clear()
83
+ self._sync_env()
84
+ logger.info("Environment variables reloaded.")
@@ -0,0 +1,3 @@
1
+ from ._retrieve_object_mixin import RetrieveObjectMixin
2
+
3
+ __all__ = ["RetrieveObjectMixin"]
@@ -0,0 +1,59 @@
1
+ from typing import Any
2
+
3
+ from django.core.exceptions import ImproperlyConfigured
4
+ from django.db.models import Model, QuerySet
5
+ from django.http import Http404
6
+
7
+
8
+ class RetrieveObjectMixin[T: Model]:
9
+ """
10
+ Retrieve a single model object by filters.
11
+
12
+ Requires the `queryset` attribute to be set in the class that inherits this mixin.
13
+
14
+ Raises `Http404` when the object is missing.
15
+
16
+ This works in both Django views and DRF views.
17
+
18
+ Example:
19
+ ```
20
+ class MyView(RetrieveModelMixin[Book], APIView):
21
+ queryset = Book.objects.all()
22
+
23
+ def get(self, request, *args, **kwargs):
24
+ obj = self.get_object(id=1)
25
+ return JsonResponse(obj.to_dict())
26
+ ```
27
+ """
28
+
29
+ queryset: QuerySet[T] | None = None
30
+
31
+ def get_object(self, **filters: Any) -> T:
32
+ """Retrieve a model object based on provided filters."""
33
+
34
+ if self.queryset is None:
35
+ raise ImproperlyConfigured(
36
+ "Queryset attribute is not set in the class.",
37
+ )
38
+
39
+ try:
40
+ return self.queryset.get(**filters)
41
+ except self.queryset.model.DoesNotExist:
42
+ raise Http404(self.not_found_detail())
43
+
44
+ def not_found_detail(self) -> dict[str, str] | str:
45
+ """
46
+ Hook for customizing the 404 message.
47
+ Can be overridden per view.
48
+ """
49
+
50
+ if self.queryset is None:
51
+ raise ImproperlyConfigured(
52
+ "Queryset attribute is not set in the class.",
53
+ )
54
+
55
+ verbose_name = self.queryset.model._meta.verbose_name
56
+ model_name = (
57
+ verbose_name.title() if verbose_name else self.queryset.model.__name__
58
+ )
59
+ return f"The requested {model_name} was not found."
@@ -342,13 +342,11 @@ wheels = [
342
342
 
343
343
  [[package]]
344
344
  name = "djresttoolkit"
345
- version = "0.8.0"
345
+ version = "1.0.0"
346
346
  source = { editable = "." }
347
347
  dependencies = [
348
348
  { name = "faker" },
349
349
  { name = "pydantic" },
350
- { name = "pydantic-settings" },
351
- { name = "pyyaml" },
352
350
  ]
353
351
 
354
352
  [package.optional-dependencies]
@@ -380,9 +378,7 @@ requires-dist = [
380
378
  { name = "faker", specifier = ">=37.5.3" },
381
379
  { name = "mypy", marker = "extra == 'dev'" },
382
380
  { name = "pydantic", specifier = ">=2.11.7" },
383
- { name = "pydantic-settings", specifier = ">=2.10.1" },
384
381
  { name = "pytest", marker = "extra == 'dev'" },
385
- { name = "pyyaml", specifier = ">=6.0.2" },
386
382
  { name = "ruff", marker = "extra == 'dev'" },
387
383
  ]
388
384
  provides-extras = ["dev"]
@@ -1,7 +0,0 @@
1
- """
2
- URL configuration for todos app.
3
- """
4
-
5
- from django.urls import path
6
-
7
- urlpatterns = []
File without changes
@@ -1,3 +0,0 @@
1
- from .env_settings import env_settings
2
-
3
- __all__ = ["env_settings"]