django-pfx 1.4.dev80__tar.gz → 1.4.dev82__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 (184) hide show
  1. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/PKG-INFO +1 -1
  2. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/django_pfx.egg-info/SOURCES.txt +3 -0
  4. django_pfx-1.4.dev82/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  5. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +16 -6
  6. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/__init__.py +1 -0
  7. django_pfx-1.4.dev82/pfx/pfxcore/models/ordered_model_mixin.py +140 -0
  8. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/__init__.py +1 -0
  9. django_pfx-1.4.dev82/pfx/pfxcore/views/ordered_rest_view_mixin.py +54 -0
  10. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/rest_views.py +6 -2
  11. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/setup.cfg +1 -0
  12. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/__init__.py +1 -0
  13. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_client.py +2 -1
  14. django_pfx-1.4.dev82/tests/tests/test_ordered_rest_view_mixin.py +498 -0
  15. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/views.py +9 -0
  16. django_pfx-1.4.dev80/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  17. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/.gitignore +0 -0
  18. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/.gitlab-ci.yml +0 -0
  19. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/.pre-commit-config.yaml +0 -0
  20. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/LICENSE +0 -0
  21. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/MANIFEST.in +0 -0
  22. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/README.md +0 -0
  23. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/django_pfx.egg-info/dependency_links.txt +0 -0
  24. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/django_pfx.egg-info/requires.txt +0 -0
  25. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/django_pfx.egg-info/top_level.txt +0 -0
  26. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/Makefile +0 -0
  27. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/conf.py +0 -0
  28. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/index.rst +0 -0
  29. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/api.views.rst +0 -0
  30. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/authentication.md +0 -0
  31. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/decorator.md +0 -0
  32. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/generate_openapi.md +0 -0
  33. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/getting_started.md +0 -0
  34. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/internationalisation.md +0 -0
  35. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/model.md +0 -0
  36. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/pfx_views.md +0 -0
  37. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/profiling.md +0 -0
  38. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/settings.md +0 -0
  39. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/doc/source/testing.md +0 -0
  40. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/img/pfx.png +0 -0
  41. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/img/pfx.svg +0 -0
  42. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/make_messages +0 -0
  43. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/manage.py +0 -0
  44. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/__init__.py +0 -0
  45. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/__init__.py +0 -0
  46. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/apidoc/__init__.py +0 -0
  47. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/apidoc/parameters.py +0 -0
  48. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/apidoc/schema.py +0 -0
  49. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/apidoc/tags.py +0 -0
  50. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/apps.py +0 -0
  51. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/decorator/__init__.py +0 -0
  52. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/decorator/rest.py +0 -0
  53. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/default_settings.py +0 -0
  54. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/exceptions.py +0 -0
  55. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/fields.py +0 -0
  56. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/http/__init__.py +0 -0
  57. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/http/json_response.py +0 -0
  58. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/management/__init__.py +0 -0
  59. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/management/commands/__init__.py +0 -0
  60. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  61. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/management/commands/profile.py +0 -0
  62. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/middleware/__init__.py +0 -0
  63. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/middleware/authentication.py +0 -0
  64. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/middleware/locale.py +0 -0
  65. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/middleware/profiling.py +0 -0
  66. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  67. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  68. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  69. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/__init__.py +0 -0
  70. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  71. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  72. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  73. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/cache_mixins.py +0 -0
  74. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/login_ban.py +0 -0
  75. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/not_null_fields.py +0 -0
  76. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/otp_user_mixin.py +0 -0
  77. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/pfx_models.py +0 -0
  78. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/pfx_user.py +0 -0
  79. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  80. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/serializers/__init__.py +0 -0
  81. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/serializers/json.py +0 -0
  82. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/settings.py +0 -0
  83. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/shortcuts.py +0 -0
  84. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/storage/__init__.py +0 -0
  85. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/storage/s3_storage.py +0 -0
  86. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  87. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  88. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  89. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  90. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  91. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  92. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/test.py +0 -0
  93. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/urls.py +0 -0
  94. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/authentication_views.py +0 -0
  95. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/fields.py +0 -0
  96. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/filters_views.py +0 -0
  97. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/locale_views.py +0 -0
  98. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  99. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  100. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/groups.py +0 -0
  101. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  102. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  103. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  104. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  105. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  106. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  107. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  108. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  109. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  110. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset.py +0 -0
  111. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  112. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  113. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  114. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  115. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  116. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/settings/__init__.py +0 -0
  117. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pfx/settings/dev.py +0 -0
  118. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/pyproject.toml +0 -0
  119. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/requirements.txt +0 -0
  120. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/serve-doc +0 -0
  121. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/setup.py +0 -0
  122. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/__init__.py +0 -0
  123. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  124. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/migrations/0001_initial.py +0 -0
  125. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/migrations/__init__.py +0 -0
  126. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/models.py +0 -0
  127. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/__init__.py +0 -0
  128. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/ci.py +0 -0
  129. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/common.py +0 -0
  130. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/dev.py +0 -0
  131. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/dev_custom_example.py +0 -0
  132. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/settings/dev_default.py +0 -0
  133. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/basic_api_errors.py +0 -0
  134. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/basic_api_test.py +0 -0
  135. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_api_doc.py +0 -0
  136. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_api_doc_search.py +0 -0
  137. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_auth_api.py +0 -0
  138. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_body_mixin.py +0 -0
  139. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_cache.py +0 -0
  140. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_fields.py +0 -0
  141. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_filters.py +0 -0
  142. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_locale_api.py +0 -0
  143. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_perm_tests.py +0 -0
  144. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_permissions.py +0 -0
  145. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_perms_api.py +0 -0
  146. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_post_migrate_groups_update.py +0 -0
  147. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_profiling_middleware.py +0 -0
  148. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_settings.py +0 -0
  149. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_shortcuts.py +0 -0
  150. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_timezone_middleware.py +0 -0
  151. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_tools.py +0 -0
  152. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_user_queryset.py +0 -0
  153. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_view_decorators.py +0 -0
  154. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/tests/test_view_fields.py +0 -0
  155. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests/urls.py +0 -0
  156. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/__init__.py +0 -0
  157. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/migrations/0001_initial.py +0 -0
  158. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/migrations/__init__.py +0 -0
  159. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/__init__.py +0 -0
  160. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/ci.py +0 -0
  161. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/common.py +0 -0
  162. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/dev.py +0 -0
  163. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/dev_custom_example.py +0 -0
  164. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/settings/dev_default.py +0 -0
  165. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/tests/__init__.py +0 -0
  166. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/tests/test_api.py +0 -0
  167. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/tests/test_auth_api.py +0 -0
  168. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/urls.py +0 -0
  169. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_base_user/views.py +0 -0
  170. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/__init__.py +0 -0
  171. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/migrations/0001_initial.py +0 -0
  172. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/migrations/__init__.py +0 -0
  173. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/models.py +0 -0
  174. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/__init__.py +0 -0
  175. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/ci.py +0 -0
  176. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/common.py +0 -0
  177. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/dev.py +0 -0
  178. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/dev_custom_example.py +0 -0
  179. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/settings/dev_default.py +0 -0
  180. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/tests/__init__.py +0 -0
  181. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/tests/test_api.py +0 -0
  182. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/tests/test_auth_api.py +0 -0
  183. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/urls.py +0 -0
  184. {django_pfx-1.4.dev80 → django_pfx-1.4.dev82}/tests_custom_user/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: django-pfx
3
- Version: 1.4.dev80
3
+ Version: 1.4.dev82
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.2
2
2
  Name: django-pfx
3
- Version: 1.4.dev80
3
+ Version: 1.4.dev82
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
@@ -71,6 +71,7 @@ pfx/pfxcore/models/abstract_pfx_base_user.py
71
71
  pfx/pfxcore/models/cache_mixins.py
72
72
  pfx/pfxcore/models/login_ban.py
73
73
  pfx/pfxcore/models/not_null_fields.py
74
+ pfx/pfxcore/models/ordered_model_mixin.py
74
75
  pfx/pfxcore/models/otp_user_mixin.py
75
76
  pfx/pfxcore/models/pfx_models.py
76
77
  pfx/pfxcore/models/pfx_user.py
@@ -90,6 +91,7 @@ pfx/pfxcore/views/authentication_views.py
90
91
  pfx/pfxcore/views/fields.py
91
92
  pfx/pfxcore/views/filters_views.py
92
93
  pfx/pfxcore/views/locale_views.py
94
+ pfx/pfxcore/views/ordered_rest_view_mixin.py
93
95
  pfx/pfxcore/views/rest_views.py
94
96
  pfx/pfxcore/views/parameters/__init__.py
95
97
  pfx/pfxcore/views/parameters/date_format.py
@@ -136,6 +138,7 @@ tests/tests/test_client.py
136
138
  tests/tests/test_fields.py
137
139
  tests/tests/test_filters.py
138
140
  tests/tests/test_locale_api.py
141
+ tests/tests/test_ordered_rest_view_mixin.py
139
142
  tests/tests/test_perm_tests.py
140
143
  tests/tests/test_permissions.py
141
144
  tests/tests/test_perms_api.py
@@ -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-01-29 12:33+0100\n"
10
+ "POT-Creation-Date: 2025-01-31 09:52+0100\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -267,27 +267,37 @@ msgstr "Un nouveau code d'authentification a été envoyé par e-mail."
267
267
  msgid "Invalid value for {filter} filter"
268
268
  msgstr "Valeur invalide pour le filtre {filter}"
269
269
 
270
- #: views/rest_views.py:242
270
+ #: views/ordered_rest_view_mixin.py:32
271
+ #, python-brace-format
272
+ msgid "object parameter is mandatory for move={move}."
273
+ msgstr "Le paramètre object est requis pour move={move}."
274
+
275
+ #: views/ordered_rest_view_mixin.py:39
276
+ #, python-brace-format
277
+ msgid "object {pk} does not exists in this move context."
278
+ msgstr "object {pk} n'existe pas dans ce contexte de déplacement."
279
+
280
+ #: views/rest_views.py:246
271
281
  #, python-brace-format
272
282
  msgid "{obj} cannot be deleted because it is referenced by other objects."
273
283
  msgstr ""
274
284
  "{obj} ne peut pas être supprimé car il est référencé par d’autres objets."
275
285
 
276
- #: views/rest_views.py:327
286
+ #: views/rest_views.py:331
277
287
  #, python-brace-format
278
288
  msgid "{model} {obj} created."
279
289
  msgstr "{model} {obj} créé."
280
290
 
281
- #: views/rest_views.py:328
291
+ #: views/rest_views.py:332
282
292
  #, python-brace-format
283
293
  msgid "{model} {obj} updated."
284
294
  msgstr "{model} {obj} modifié."
285
295
 
286
- #: views/rest_views.py:1153
296
+ #: views/rest_views.py:1157
287
297
  #, python-brace-format
288
298
  msgid "{model} {obj} deleted."
289
299
  msgstr "{model} {obj} supprimé."
290
300
 
291
- #: views/rest_views.py:1252 views/rest_views.py:1292
301
+ #: views/rest_views.py:1256 views/rest_views.py:1296
292
302
  msgid "Unexpected storage error"
293
303
  msgstr "Erreur de stockage inattendue"
@@ -6,6 +6,7 @@ from .not_null_fields import (
6
6
  NotNullTextField,
7
7
  NotNullURLField,
8
8
  )
9
+ from .ordered_model_mixin import OrderedModelMixin
9
10
  from .otp_user_mixin import OtpUserMixin
10
11
  from .pfx_models import (
11
12
  ErrorMessageMixin,
@@ -0,0 +1,140 @@
1
+ from django.db import models
2
+ from django.db.models import F, Max, Min
3
+
4
+
5
+ class OrderedModelMixin(models.Model):
6
+ ordered_by = []
7
+ ordered_default = 'last'
8
+
9
+ seq = models.PositiveBigIntegerField("Séquence")
10
+
11
+ class Meta:
12
+ abstract = True
13
+
14
+ @property
15
+ def _ordered_by_values(self):
16
+ return {self.serializable_value(f) for f in self.ordered_by}
17
+
18
+ def __init__(self, *args, **kwargs):
19
+ super().__init__(*args, **kwargs)
20
+ self.__previous_ordered_by_values = self._ordered_by_values
21
+
22
+ def clean_fields(self, exclude=None):
23
+ if not self.seq:
24
+ self.seq = self._order_default
25
+ super().clean_fields(exclude=exclude)
26
+
27
+ def save(self, *args, **kwargs):
28
+ if not self.seq:
29
+ self.seq = self._order_default
30
+ super().save(*args, **kwargs)
31
+ if self.__previous_ordered_by_values != self._ordered_by_values:
32
+ if self.ordered_default == 'first':
33
+ self.top()
34
+ else:
35
+ self.bottom()
36
+
37
+ @property
38
+ def _order_qs(self):
39
+ return self.__class__._default_manager.filter(**{
40
+ f: getattr(self, f) for f in self.ordered_by})
41
+
42
+ @property
43
+ def _order_max(self):
44
+ return self._order_qs.aggregate(Max('seq'))['seq__max']
45
+
46
+ @property
47
+ def _order_min(self):
48
+ return self._order_qs.aggregate(Min('seq'))['seq__min']
49
+
50
+ @property
51
+ def _order_default(self):
52
+ if self.ordered_default == 'first':
53
+ min = self._order_min
54
+ res = min is None and 1 or min - 1
55
+ if res == 0:
56
+ self.first._order_shift()
57
+ return 1
58
+ return res
59
+ else:
60
+ return (self._order_max or 0) + 1
61
+
62
+ @property
63
+ def previous(self):
64
+ return self._order_qs.filter(
65
+ seq__lt=self.seq).order_by('seq', 'pk').last()
66
+
67
+ @property
68
+ def next(self):
69
+ return self._order_qs.filter(
70
+ seq__gt=self.seq).order_by('seq', 'pk').first()
71
+
72
+ @property
73
+ def first(self):
74
+ return self._order_qs.order_by('seq', 'pk').first()
75
+
76
+ @property
77
+ def last(self):
78
+ return self._order_qs.order_by('seq', 'pk').last()
79
+
80
+ def _order_shift(self):
81
+ self._order_qs.filter(seq__gte=self.seq).update(
82
+ seq=F('seq') + 1)
83
+
84
+ def _order_switch(self, other):
85
+ other_seq = other.seq
86
+ other.seq = self.seq
87
+ other.save(update_fields=['seq'])
88
+ self.seq = other_seq
89
+ self.save(update_fields=['seq'])
90
+
91
+ def up(self):
92
+ previous = self.previous
93
+ if not previous:
94
+ return
95
+ self._order_switch(previous)
96
+
97
+ def down(self):
98
+ next = self.next
99
+ if not next:
100
+ return
101
+ self._order_switch(next)
102
+
103
+ def top(self):
104
+ first = self.first
105
+ if first.pk == self.pk:
106
+ return
107
+ seq = first.seq - 1
108
+ if seq == 0:
109
+ first._order_shift()
110
+ seq = 1
111
+ self.seq = seq
112
+ self.save(update_fields=['seq'])
113
+
114
+ def bottom(self):
115
+ last = self.last
116
+ if last.pk == self.pk:
117
+ return
118
+ self.seq = last.seq + 1
119
+ self.save(update_fields=['seq'])
120
+
121
+ def above(self, other):
122
+ prev = other.previous
123
+ if not prev:
124
+ return self.top()
125
+ seq = other.seq - 1
126
+ if seq == prev.seq:
127
+ other._order_shift()
128
+ seq += 1
129
+ self.seq = seq
130
+ self.save(update_fields=['seq'])
131
+
132
+ def below(self, other):
133
+ next = other.next
134
+ if not next:
135
+ return self.bottom()
136
+ seq = other.seq + 1
137
+ if seq == next.seq:
138
+ next._order_shift()
139
+ self.seq = seq
140
+ self.save(update_fields=['seq'])
@@ -8,6 +8,7 @@ from .authentication_views import (
8
8
  from .fields import VF, FieldType, ViewField, ViewModelField
9
9
  from .filters_views import Filter, FilterGroup, ModelFilter
10
10
  from .locale_views import LocaleRestView
11
+ from .ordered_rest_view_mixin import OrderedRestViewMixin
11
12
  from .rest_views import (
12
13
  BaseRestView,
13
14
  BodyMixin,
@@ -0,0 +1,54 @@
1
+
2
+ from django.core.exceptions import ObjectDoesNotExist
3
+ from django.db import transaction
4
+ from django.utils.translation import gettext_lazy as _
5
+
6
+ from pfx.pfxcore.exceptions import APIError
7
+ from pfx.pfxcore.models import OrderedModelMixin
8
+ from pfx.pfxcore.shortcuts import f
9
+
10
+ from .rest_views import ModelResponseMixin
11
+
12
+
13
+ class OrderedRestViewMixin(ModelResponseMixin):
14
+ """Extension mixin for OrderedModelMixin models."""
15
+
16
+ def __init__(self, *args, **kwargs):
17
+ if not issubclass(self.model, OrderedModelMixin):
18
+ raise TypeError("model is not a subclass of OrderedModelMixin")
19
+ super().__init__(*args, **kwargs)
20
+
21
+ def is_valid(self, obj, created=False, **kwargs):
22
+ with transaction.atomic():
23
+ res = super().is_valid(obj, created, **kwargs)
24
+ self.apply_move(obj)
25
+ return res
26
+
27
+ def apply_move(self, obj):
28
+ def get_object(move):
29
+ pk = self.request.GET.get('object')
30
+ if not pk:
31
+ raise APIError(f(
32
+ _("object parameter is mandatory for move={move}."),
33
+ move=move))
34
+ try:
35
+ return self.get_queryset(
36
+ from_queryset=obj._order_qs).get(pk=pk)
37
+ except ObjectDoesNotExist:
38
+ raise APIError(f(
39
+ _("object {pk} does not exists in this move context."),
40
+ pk=pk))
41
+
42
+ move = self.request.GET.get('move')
43
+ if move == 'up':
44
+ obj.up()
45
+ elif move == 'down':
46
+ obj.down()
47
+ elif move == 'bottom':
48
+ obj.bottom()
49
+ elif move == 'top':
50
+ obj.top()
51
+ elif move == 'above':
52
+ obj.above(get_object(move))
53
+ elif move == 'below':
54
+ obj.below(get_object(move))
@@ -80,7 +80,9 @@ class ModelMixin():
80
80
  raise Exception("The queryset must be a UserFilteredQuerySetMixin")
81
81
  return qs
82
82
 
83
- def get_queryset(self, select_related=None, prefetch_related=None):
83
+ def get_queryset(
84
+ self, select_related=None, prefetch_related=None,
85
+ from_queryset=None):
84
86
  """Get the queryset for the view model.
85
87
 
86
88
  The returned queryset is filtered according to user rights.
@@ -89,10 +91,12 @@ class ModelMixin():
89
91
  :type select_related: :class:`list[str]`
90
92
  :param prefetch_related: Arguments for queryset prefetch_related
91
93
  :type prefetch_related: :class:`list[str]`
94
+ :param from_queryset: A source queryset
92
95
  :returns: The queryset
93
96
  :rtype: :class:`django.db.models.QuerySet`
94
97
  """
95
- qs = self.apply_user_filter(self.model._default_manager.all())
98
+ qs = self.apply_user_filter(
99
+ from_queryset or self.model._default_manager.all())
96
100
  if select_related:
97
101
  qs = qs.select_related(*select_related)
98
102
  if prefetch_related:
@@ -69,6 +69,7 @@ line_length = 79
69
69
 
70
70
  [coverage:run]
71
71
  omit =
72
+ manage.py
72
73
  tests/*
73
74
  setup.py
74
75
  pfx/pfxcore/apps.py
@@ -9,6 +9,7 @@ from .test_client import TestApiClient
9
9
  from .test_fields import FieldsTest
10
10
  from .test_filters import FiltersTest
11
11
  from .test_locale_api import LocaleAPITest
12
+ from .test_ordered_rest_view_mixin import TestOrderedRestViewMixin
12
13
  from .test_perm_tests import PermTestsTest
13
14
  from .test_permissions import TestPermissions
14
15
  from .test_perms_api import PermsAPITest
@@ -11,6 +11,7 @@ from pfx.pfxcore.models import JSONReprMixin
11
11
  from pfx.pfxcore.test import APIClient, TestAssertMixin
12
12
  from pfx.pfxcore.views import RestView
13
13
  from tests.models import User
14
+ from tests.views import FakeViewMixin
14
15
 
15
16
 
16
17
  class TestModel(JSONReprMixin, models.Model):
@@ -26,7 +27,7 @@ class TestModel(JSONReprMixin, models.Model):
26
27
 
27
28
 
28
29
  @rest_view("/test")
29
- class TestRestView(RestView):
30
+ class TestRestView(FakeViewMixin, RestView):
30
31
  default_public = True
31
32
  model = TestModel
32
33