django-pfx 1.4.dev136__tar.gz → 1.4.dev138__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 (197) hide show
  1. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/PKG-INFO +1 -1
  2. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/fields/media_field.py +24 -12
  4. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +5 -5
  5. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/media_rest_view_mixin.py +13 -0
  6. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/rest_views.py +18 -10
  7. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/basic_api_test.py +2 -5
  8. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/.gitignore +0 -0
  9. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/.gitlab-ci.yml +0 -0
  10. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/.pre-commit-config.yaml +0 -0
  11. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/LICENSE +0 -0
  12. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/MANIFEST.in +0 -0
  13. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/README.md +0 -0
  14. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/django_pfx.egg-info/SOURCES.txt +0 -0
  15. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/django_pfx.egg-info/dependency_links.txt +0 -0
  16. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/django_pfx.egg-info/requires.txt +0 -0
  17. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/django_pfx.egg-info/top_level.txt +0 -0
  18. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/Makefile +0 -0
  19. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/conf.py +0 -0
  20. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/index.rst +0 -0
  21. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/api.views.rst +0 -0
  22. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/authentication.md +0 -0
  23. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/decorator.md +0 -0
  24. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/generate_openapi.md +0 -0
  25. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/getting_started.md +0 -0
  26. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/internationalisation.md +0 -0
  27. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/model.md +0 -0
  28. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/pfx_views.md +0 -0
  29. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/profiling.md +0 -0
  30. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/settings.md +0 -0
  31. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/doc/source/testing.md +0 -0
  32. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/img/pfx.png +0 -0
  33. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/img/pfx.svg +0 -0
  34. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/make_messages +0 -0
  35. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/manage.py +0 -0
  36. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/__init__.py +0 -0
  37. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/__init__.py +0 -0
  38. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/apidoc/__init__.py +0 -0
  39. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/apidoc/parameters.py +0 -0
  40. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/apidoc/schema.py +0 -0
  41. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/apidoc/tags.py +0 -0
  42. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/apps.py +0 -0
  43. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/decorator/__init__.py +0 -0
  44. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/decorator/rest.py +0 -0
  45. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/default_settings.py +0 -0
  46. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/exceptions.py +0 -0
  47. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/fields/__init__.py +0 -0
  48. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/fields/decimal_field.py +0 -0
  49. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  50. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/fields/nh3_field.py +0 -0
  51. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/http/__init__.py +0 -0
  52. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/http/json_response.py +0 -0
  53. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  54. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/management/__init__.py +0 -0
  55. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/management/commands/__init__.py +0 -0
  56. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  57. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/management/commands/profile.py +0 -0
  58. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/middleware/__init__.py +0 -0
  59. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/middleware/authentication.py +0 -0
  60. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/middleware/locale.py +0 -0
  61. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/middleware/profiling.py +0 -0
  62. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  63. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  64. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  65. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/__init__.py +0 -0
  66. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  67. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  68. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/__init__.py +0 -0
  69. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  70. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/cache_mixins.py +0 -0
  71. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/login_ban.py +0 -0
  72. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/not_null_fields.py +0 -0
  73. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  74. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/otp_user_mixin.py +0 -0
  75. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/pfx_models.py +0 -0
  76. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/pfx_user.py +0 -0
  77. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  78. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/serializers/__init__.py +0 -0
  79. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/serializers/json.py +0 -0
  80. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/settings.py +0 -0
  81. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/shortcuts.py +0 -0
  82. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/storage/__init__.py +0 -0
  83. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/storage/exceptions.py +0 -0
  84. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/storage/local_storage.py +0 -0
  85. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/storage/s3_storage.py +0 -0
  86. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  87. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  88. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  89. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  90. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  91. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  92. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/test.py +0 -0
  93. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/urls.py +0 -0
  94. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/__init__.py +0 -0
  95. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/authentication_views.py +0 -0
  96. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/fields.py +0 -0
  97. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/filters_views.py +0 -0
  98. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/locale_views.py +0 -0
  99. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  100. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  101. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  102. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/groups.py +0 -0
  103. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  104. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  105. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  106. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  107. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  108. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  109. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  110. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  111. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  112. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset.py +0 -0
  113. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  114. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  115. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  116. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  117. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  118. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/settings/__init__.py +0 -0
  119. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pfx/settings/dev.py +0 -0
  120. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/pyproject.toml +0 -0
  121. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/requirements.txt +0 -0
  122. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/serve-doc +0 -0
  123. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/setup.cfg +0 -0
  124. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/setup.py +0 -0
  125. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/__init__.py +0 -0
  126. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/apps.py +0 -0
  127. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  128. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/migrations/0001_initial.py +0 -0
  129. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/migrations/0002_alter_book_cover.py +0 -0
  130. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/migrations/0003_book_local_file.py +0 -0
  131. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/migrations/__init__.py +0 -0
  132. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/models.py +0 -0
  133. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/__init__.py +0 -0
  134. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/ci.py +0 -0
  135. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/common.py +0 -0
  136. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/dev.py +0 -0
  137. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/dev_custom_example.py +0 -0
  138. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/settings/dev_default.py +0 -0
  139. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/__init__.py +0 -0
  140. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/basic_api_errors.py +0 -0
  141. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_api_doc.py +0 -0
  142. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_api_doc_search.py +0 -0
  143. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_auth_api.py +0 -0
  144. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_body_mixin.py +0 -0
  145. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_cache.py +0 -0
  146. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_client.py +0 -0
  147. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_fields_choices.py +0 -0
  148. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_fields_date.py +0 -0
  149. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_fields_decimal.py +0 -0
  150. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_fields_minutes_duration.py +0 -0
  151. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_fields_nh3.py +0 -0
  152. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_filters.py +0 -0
  153. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_locale_api.py +0 -0
  154. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  155. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_perm_tests.py +0 -0
  156. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_permissions.py +0 -0
  157. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_perms_api.py +0 -0
  158. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_post_migrate_groups_update.py +0 -0
  159. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_profiling_middleware.py +0 -0
  160. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_settings.py +0 -0
  161. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_shortcuts.py +0 -0
  162. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_timezone_middleware.py +0 -0
  163. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_tools.py +0 -0
  164. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_user_queryset.py +0 -0
  165. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_view_decorators.py +0 -0
  166. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/tests/test_view_fields.py +0 -0
  167. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/urls.py +0 -0
  168. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests/views.py +0 -0
  169. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/__init__.py +0 -0
  170. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/migrations/0001_initial.py +0 -0
  171. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/migrations/__init__.py +0 -0
  172. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/__init__.py +0 -0
  173. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/ci.py +0 -0
  174. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/common.py +0 -0
  175. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/dev.py +0 -0
  176. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/dev_custom_example.py +0 -0
  177. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/settings/dev_default.py +0 -0
  178. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/tests/__init__.py +0 -0
  179. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/tests/test_api.py +0 -0
  180. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/tests/test_auth_api.py +0 -0
  181. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/urls.py +0 -0
  182. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_base_user/views.py +0 -0
  183. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/__init__.py +0 -0
  184. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/migrations/0001_initial.py +0 -0
  185. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/migrations/__init__.py +0 -0
  186. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/models.py +0 -0
  187. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/__init__.py +0 -0
  188. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/ci.py +0 -0
  189. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/common.py +0 -0
  190. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/dev.py +0 -0
  191. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/dev_custom_example.py +0 -0
  192. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/settings/dev_default.py +0 -0
  193. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/tests/__init__.py +0 -0
  194. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/tests/test_api.py +0 -0
  195. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/tests/test_auth_api.py +0 -0
  196. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/urls.py +0 -0
  197. {django_pfx-1.4.dev136 → django_pfx-1.4.dev138}/tests_custom_user/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.4.dev136
3
+ Version: 1.4.dev138
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.4.dev136
3
+ Version: 1.4.dev138
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -3,7 +3,7 @@ from importlib import import_module
3
3
  from urllib.request import urlopen
4
4
 
5
5
  from django.db import models
6
- from django.db.models.signals import post_delete
6
+ from django.db.models.signals import post_delete, post_init
7
7
  from django.dispatch import receiver
8
8
 
9
9
  from pfx.pfxcore.shortcuts import settings
@@ -27,6 +27,7 @@ class MediaField(models.JSONField):
27
27
  "class on the field or define STORAGE_DEFAULT settings.")
28
28
  self.storage = storage or get_storage_class(settings.STORAGE_DEFAULT)
29
29
  self.auto_delete = auto_delete
30
+ self._db_value = None
30
31
  super().__init__(
31
32
  *args, max_length=max_length, **kwargs)
32
33
 
@@ -34,24 +35,28 @@ class MediaField(models.JSONField):
34
35
  def get_default_key(obj, filename):
35
36
  return f"{type(obj).__name__}/{obj.pk}/{filename}"
36
37
 
37
- def clean(self, value, obj):
38
+ def media_pre_save(self, obj):
38
39
  def save_file(obj, file, name):
39
40
  setattr(obj, self.name, self.upload(obj, file, name))
40
41
  obj.save(update_fields={self.name})
41
42
 
43
+ after_save = []
44
+ value = self.value_from_object(obj)
42
45
  if isinstance(value, dict):
43
- toDelete = value.pop('toDelete', None)
44
46
  b64 = value.pop('base64', None)
45
47
  name = value.get('name')
46
- if toDelete:
47
- obj._after_save.append(lambda: self.delete(toDelete))
48
- value = None
49
- if b64:
50
- with urlopen(b64) as response:
51
- file = response.read()
52
- value = dict(key=self.get_key(obj, file))
53
- obj._after_save.append(lambda: save_file(obj, file, name))
54
- return super().clean(value, obj)
48
+ else:
49
+ b64 = None
50
+
51
+ if self._db_value and (b64 or not value):
52
+ after_save.append(lambda: self.delete(self._db_value))
53
+ setattr(obj, self.name, None)
54
+ if b64:
55
+ with urlopen(b64) as response:
56
+ file = response.read()
57
+ setattr(obj, self.name, dict(key=self.get_key(obj, file)))
58
+ after_save.append(lambda: save_file(obj, file, name))
59
+ return after_save
55
60
 
56
61
  def to_python(self, value):
57
62
  return super().to_python(self.storage.to_python(value))
@@ -73,6 +78,13 @@ class MediaField(models.JSONField):
73
78
  return self.storage.delete(value)
74
79
 
75
80
 
81
+ @receiver(post_init)
82
+ def post_init_media(sender, instance, **kwargs):
83
+ for field in sender._meta.fields:
84
+ if isinstance(field, MediaField):
85
+ field._db_value = field.value_from_object(instance)
86
+
87
+
76
88
  @receiver(post_delete)
77
89
  def post_delete_media(sender, instance, **kwargs):
78
90
  for field in sender._meta.fields:
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: \n"
9
9
  "Report-Msgid-Bugs-To: \n"
10
- "POT-Creation-Date: 2025-06-04 16:47+0200\n"
10
+ "POT-Creation-Date: 2025-06-17 08:53+0200\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -272,7 +272,7 @@ msgstr "Un nouveau code d'authentification a été envoyé par e-mail."
272
272
  msgid "Invalid value for {filter} filter"
273
273
  msgstr "Valeur invalide pour le filtre {filter}"
274
274
 
275
- #: views/media_rest_view_mixin.py:37 views/media_rest_view_mixin.py:123
275
+ #: views/media_rest_view_mixin.py:37 views/media_rest_view_mixin.py:130
276
276
  msgid "Unexpected storage error"
277
277
  msgstr "Erreur de stockage inattendue"
278
278
 
@@ -292,17 +292,17 @@ msgid "{obj} cannot be deleted because it is referenced by other objects."
292
292
  msgstr ""
293
293
  "{obj} ne peut pas être supprimé car il est référencé par d’autres objets."
294
294
 
295
- #: views/rest_views.py:319
295
+ #: views/rest_views.py:331
296
296
  #, python-brace-format
297
297
  msgid "{model} {obj} created."
298
298
  msgstr "{model} {obj} créé."
299
299
 
300
- #: views/rest_views.py:320
300
+ #: views/rest_views.py:332
301
301
  #, python-brace-format
302
302
  msgid "{model} {obj} updated."
303
303
  msgstr "{model} {obj} modifié."
304
304
 
305
- #: views/rest_views.py:1174
305
+ #: views/rest_views.py:1182
306
306
  #, python-brace-format
307
307
  msgid "{model} {obj} deleted."
308
308
  msgstr "{model} {obj} supprimé."
@@ -59,6 +59,13 @@ def get_media_field_response(obj, field, request):
59
59
  class MediaRestViewMixin(ModelMixin):
60
60
  """Extension mixin to manage media fields."""
61
61
 
62
+ def __init__(self, *args, **kw):
63
+ super().__init__(*args, **kw)
64
+ self.media_fields = set()
65
+ for field in self.model._meta.fields:
66
+ if isinstance(field, MediaField):
67
+ self.media_fields.add(field)
68
+
62
69
  @rest_api(
63
70
  "/<int:pk>/<str:field>/upload-url/<str:filename>", method="get",
64
71
  priority_doc=-8)
@@ -165,6 +172,12 @@ class MediaRestViewMixin(ModelMixin):
165
172
  obj = self.get_object(pk=pk)
166
173
  return get_media_field_response(obj, field, self.request)
167
174
 
175
+ def pre_save(self, obj, created=False):
176
+ funcs = super().pre_save(obj, created=created)
177
+ for field in self.media_fields:
178
+ funcs.extend(field.media_pre_save(obj))
179
+ return funcs
180
+
168
181
 
169
182
  class MediaPermsRestViewMixin(MediaRestViewMixin):
170
183
  """Extension mixin to check permissions."""
@@ -247,6 +247,18 @@ class ModelMixin():
247
247
  """
248
248
  return model_permissions(cls.model, actions)
249
249
 
250
+ def pre_save(self, obj, created=False):
251
+ """Return a list of function to call in post_save.
252
+ """
253
+ return []
254
+
255
+ def post_save(self, obj, created=False, funcs=None):
256
+ """Post save operations.
257
+ """
258
+ funcs = funcs or []
259
+ for func in funcs:
260
+ func()
261
+
250
262
 
251
263
  class ModelResponseMixin(ModelMixin):
252
264
  """Extension of :class:`ModelMixin` to manage object responses."""
@@ -339,17 +351,13 @@ class ModelResponseMixin(ModelMixin):
339
351
  :returns: The JSON response
340
352
  :rtype: :class:`JsonResponse`
341
353
  """
342
- if rel_data or obj._after_save:
343
- with transaction.atomic():
344
- obj.save()
345
- if rel_data:
346
- for k, v in rel_data.items():
347
- getattr(obj, k).set(v)
348
- for callback in obj._after_save:
349
- callback()
350
- obj._after_save = []
351
- else:
354
+ with transaction.atomic():
355
+ funcs = self.pre_save(obj, created=created)
352
356
  obj.save()
357
+ if rel_data:
358
+ for k, v in rel_data.items():
359
+ getattr(obj, k).set(v)
360
+ self.post_save(obj, created=created, funcs=funcs)
353
361
  obj = self.get_object(pk=obj.pk)
354
362
  return self.response(
355
363
  obj, **self.is_valid_response_meta(obj, created=created))
@@ -732,13 +732,11 @@ class BasicAPITest(TestAssertMixin, TestCase):
732
732
  'bca20547e94049e1ffea27223581c567022a5774.txt').exists())
733
733
 
734
734
  # Replace file
735
- old_file = self.get_val(response, 'local_file')
736
735
  response = self.client.put(f'/api/books/{book_pk}', dict(
737
736
  local_file=dict(
738
737
  name='test2.txt',
739
738
  base64='data:text/plain;charset=utf-8;'
740
- 'base64,TmV3IGNvbnRlbnQ=',
741
- toDelete=old_file)))
739
+ 'base64,TmV3IGNvbnRlbnQ=')))
742
740
  self.assertRC(response, 200)
743
741
  self.assertJE(
744
742
  response, 'local_file.key',
@@ -752,9 +750,8 @@ class BasicAPITest(TestAssertMixin, TestCase):
752
750
  'af9f06b2b3b1546ac44f4a02994d0ef09e074b91.txt').exists())
753
751
 
754
752
  # Delete file
755
- old_file = self.get_val(response, 'local_file')
756
753
  response = self.client.put(f'/api/books/{book_pk}', dict(
757
- local_file=dict(toDelete=old_file)))
754
+ local_file=None))
758
755
  self.assertRC(response, 200)
759
756
  self.assertJE(response, 'local_file', None)
760
757
  self.assertFalse(Path(
File without changes