django-pfx 1.5.dev2__tar.gz → 1.7.dev2__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 (198) hide show
  1. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/PKG-INFO +1 -1
  2. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/exceptions.py +19 -7
  4. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +19 -19
  5. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/otp_user_mixin.py +4 -0
  6. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/authentication_views.py +2 -1
  7. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/rest_views.py +8 -1
  8. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/basic_api_errors.py +2 -2
  9. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/.gitignore +0 -0
  10. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/.gitlab-ci.yml +0 -0
  11. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/.pre-commit-config.yaml +0 -0
  12. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/LICENSE +0 -0
  13. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/MANIFEST.in +0 -0
  14. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/README.md +0 -0
  15. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/django_pfx.egg-info/SOURCES.txt +0 -0
  16. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/django_pfx.egg-info/dependency_links.txt +0 -0
  17. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/django_pfx.egg-info/requires.txt +0 -0
  18. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/django_pfx.egg-info/top_level.txt +0 -0
  19. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/Makefile +0 -0
  20. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/conf.py +0 -0
  21. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/index.rst +0 -0
  22. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/api.views.rst +0 -0
  23. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/authentication.md +0 -0
  24. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/decorator.md +0 -0
  25. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/generate_openapi.md +0 -0
  26. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/getting_started.md +0 -0
  27. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/internationalisation.md +0 -0
  28. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/model.md +0 -0
  29. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/pfx_views.md +0 -0
  30. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/profiling.md +0 -0
  31. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/settings.md +0 -0
  32. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/doc/source/testing.md +0 -0
  33. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/img/pfx.png +0 -0
  34. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/img/pfx.svg +0 -0
  35. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/make_messages +0 -0
  36. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/manage.py +0 -0
  37. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/__init__.py +0 -0
  38. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/__init__.py +0 -0
  39. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/apidoc/__init__.py +0 -0
  40. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/apidoc/parameters.py +0 -0
  41. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/apidoc/schema.py +0 -0
  42. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/apidoc/tags.py +0 -0
  43. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/apps.py +0 -0
  44. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/decorator/__init__.py +0 -0
  45. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/decorator/rest.py +0 -0
  46. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/default_settings.py +0 -0
  47. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/fields/__init__.py +0 -0
  48. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/fields/decimal_field.py +0 -0
  49. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/fields/media_field.py +0 -0
  50. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  51. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/fields/rich_text_field.py +0 -0
  52. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/http/__init__.py +0 -0
  53. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/http/json_response.py +0 -0
  54. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  55. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/management/__init__.py +0 -0
  56. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/management/commands/__init__.py +0 -0
  57. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  58. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/management/commands/profile.py +0 -0
  59. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/middleware/__init__.py +0 -0
  60. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/middleware/authentication.py +0 -0
  61. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/middleware/locale.py +0 -0
  62. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/middleware/profiling.py +0 -0
  63. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  64. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  65. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  66. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/__init__.py +0 -0
  67. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  68. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  69. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/__init__.py +0 -0
  70. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  71. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/cache_mixins.py +0 -0
  72. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/login_ban.py +0 -0
  73. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/not_null_fields.py +0 -0
  74. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  75. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/pfx_models.py +0 -0
  76. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/pfx_user.py +0 -0
  77. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  78. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/serializers/__init__.py +0 -0
  79. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/serializers/json.py +0 -0
  80. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/settings.py +0 -0
  81. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/shortcuts.py +0 -0
  82. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/storage/__init__.py +0 -0
  83. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/storage/exceptions.py +0 -0
  84. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/storage/local_storage.py +0 -0
  85. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/storage/s3_storage.py +0 -0
  86. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  87. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  88. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  89. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  90. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  91. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  92. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/test.py +0 -0
  93. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/urls.py +0 -0
  94. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/__init__.py +0 -0
  95. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/fields.py +0 -0
  96. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/filters_views.py +0 -0
  97. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/locale_views.py +0 -0
  98. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
  99. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  100. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  101. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  102. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/groups.py +0 -0
  103. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  104. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  105. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  106. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  107. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  108. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  109. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  110. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  111. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  112. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset.py +0 -0
  113. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  114. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  115. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  116. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  117. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  118. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/settings/__init__.py +0 -0
  119. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pfx/settings/dev.py +0 -0
  120. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/pyproject.toml +0 -0
  121. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/requirements.txt +0 -0
  122. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/serve-doc +0 -0
  123. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/setup.cfg +0 -0
  124. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/setup.py +0 -0
  125. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/__init__.py +0 -0
  126. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/apps.py +0 -0
  127. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  128. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/migrations/0001_initial.py +0 -0
  129. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/migrations/0002_alter_book_cover.py +0 -0
  130. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/migrations/0003_book_local_file.py +0 -0
  131. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/migrations/__init__.py +0 -0
  132. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/models.py +0 -0
  133. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/__init__.py +0 -0
  134. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/ci.py +0 -0
  135. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/common.py +0 -0
  136. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/dev.py +0 -0
  137. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/dev_custom_example.py +0 -0
  138. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/settings/dev_default.py +0 -0
  139. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/__init__.py +0 -0
  140. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/basic_api_test.py +0 -0
  141. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_api_doc.py +0 -0
  142. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_api_doc_search.py +0 -0
  143. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_auth_api.py +0 -0
  144. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_body_mixin.py +0 -0
  145. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_cache.py +0 -0
  146. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_client.py +0 -0
  147. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_choices.py +0 -0
  148. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_date.py +0 -0
  149. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_decimal.py +0 -0
  150. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_minutes_duration.py +0 -0
  151. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_one2many.py +0 -0
  152. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_fields_rich_text.py +0 -0
  153. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_filters.py +0 -0
  154. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_locale_api.py +0 -0
  155. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  156. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_perm_tests.py +0 -0
  157. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_permissions.py +0 -0
  158. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_perms_api.py +0 -0
  159. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_post_migrate_groups_update.py +0 -0
  160. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_profiling_middleware.py +0 -0
  161. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_settings.py +0 -0
  162. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_shortcuts.py +0 -0
  163. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_timezone_middleware.py +0 -0
  164. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_tools.py +0 -0
  165. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_user_queryset.py +0 -0
  166. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_view_decorators.py +0 -0
  167. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/tests/test_view_fields.py +0 -0
  168. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/urls.py +0 -0
  169. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests/views.py +0 -0
  170. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/__init__.py +0 -0
  171. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/migrations/0001_initial.py +0 -0
  172. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/migrations/__init__.py +0 -0
  173. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/__init__.py +0 -0
  174. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/ci.py +0 -0
  175. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/common.py +0 -0
  176. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/dev.py +0 -0
  177. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/dev_custom_example.py +0 -0
  178. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/settings/dev_default.py +0 -0
  179. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/tests/__init__.py +0 -0
  180. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/tests/test_api.py +0 -0
  181. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/tests/test_auth_api.py +0 -0
  182. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/urls.py +0 -0
  183. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_base_user/views.py +0 -0
  184. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/__init__.py +0 -0
  185. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/migrations/0001_initial.py +0 -0
  186. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/migrations/__init__.py +0 -0
  187. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/models.py +0 -0
  188. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/__init__.py +0 -0
  189. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/ci.py +0 -0
  190. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/common.py +0 -0
  191. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/dev.py +0 -0
  192. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/dev_custom_example.py +0 -0
  193. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/settings/dev_default.py +0 -0
  194. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/tests/__init__.py +0 -0
  195. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/tests/test_api.py +0 -0
  196. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/tests/test_auth_api.py +0 -0
  197. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/tests_custom_user/urls.py +0 -0
  198. {django_pfx-1.5.dev2 → django_pfx-1.7.dev2}/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.5.dev2
3
+ Version: 1.7.dev2
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.5.dev2
3
+ Version: 1.7.dev2
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,4 +1,4 @@
1
- from django.core.exceptions import NON_FIELD_ERRORS
1
+ from django.core.exceptions import NON_FIELD_ERRORS, FieldDoesNotExist
2
2
  from django.utils.translation import gettext_lazy as _
3
3
 
4
4
  from pfx.pfxcore.http import JsonResponse
@@ -15,14 +15,26 @@ def validation_error_dict(e):
15
15
  class APIError(Exception):
16
16
  def __init__(
17
17
  self, message, status=400, delete_cookie=False,
18
- validation_error=None, **kwargs):
18
+ validation_error=None, validation_models=None, **kwargs):
19
+ def field(name):
20
+ for model in (validation_models or []):
21
+ try:
22
+ return model._meta.get_field(name).verbose_name
23
+ except FieldDoesNotExist:
24
+ continue
25
+ return name
26
+
19
27
  self.status = status
20
28
  if validation_error:
21
- d = validation_error_dict(validation_error)
22
- mlist = d.get(NON_FIELD_ERRORS)
23
- if mlist:
24
- message = mlist[0]
25
- self.data = dict(message=message, errors=d, **kwargs)
29
+ errors = []
30
+ errors_dict = validation_error_dict(validation_error)
31
+ for k, v in errors_dict.items():
32
+ if k == NON_FIELD_ERRORS:
33
+ errors.extend(v)
34
+ else:
35
+ errors.extend(f"{field(k)}: {e}" for e in v)
36
+ message = f"{message}\n{'\n'.join(errors)}"
37
+ self.data = dict(message=message, errors=errors_dict, **kwargs)
26
38
  else:
27
39
  self.data = dict(message=message, **kwargs)
28
40
  self.delete_cookie = delete_cookie
@@ -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: 2026-02-25 10:08+0100\n"
10
+ "POT-Creation-Date: 2026-03-05 16:44+0100\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -22,28 +22,28 @@ msgstr ""
22
22
  msgid "An internal server error occured."
23
23
  msgstr "Une erreur interne du serveur est survenue."
24
24
 
25
- #: exceptions.py:41 exceptions.py:64
25
+ #: exceptions.py:53 exceptions.py:76
26
26
  #, python-brace-format
27
27
  msgid "{model} not found."
28
28
  msgstr "{model} non trouvé."
29
29
 
30
- #: exceptions.py:48
30
+ #: exceptions.py:60
31
31
  msgid "JSON Malformed {}"
32
32
  msgstr "JSON malformé {}"
33
33
 
34
- #: exceptions.py:71
34
+ #: exceptions.py:83
35
35
  msgid "Login failed"
36
36
  msgstr "La connexion a échoué"
37
37
 
38
- #: exceptions.py:78
38
+ #: exceptions.py:90
39
39
  msgid "Unauthorized"
40
40
  msgstr "Non autorisé"
41
41
 
42
- #: exceptions.py:85
42
+ #: exceptions.py:97
43
43
  msgid "Forbidden"
44
44
  msgstr "Interdit"
45
45
 
46
- #: exceptions.py:92
46
+ #: exceptions.py:104
47
47
  msgid "Resource not found"
48
48
  msgstr "Ressource non trouvée"
49
49
 
@@ -103,7 +103,7 @@ msgstr "Compte HOTP"
103
103
  msgid "HOTP expiry"
104
104
  msgstr "Expiration HOTP"
105
105
 
106
- #: models/otp_user_mixin.py:29 views/authentication_views.py:503
106
+ #: models/otp_user_mixin.py:29 views/authentication_views.py:504
107
107
  msgid "OTP enabled"
108
108
  msgstr "OTP activé"
109
109
 
@@ -222,39 +222,39 @@ msgstr ""
222
222
  msgid "Successful login"
223
223
  msgstr "Connexion réussie"
224
224
 
225
- #: views/authentication_views.py:250 views/authentication_views.py:420
225
+ #: views/authentication_views.py:251 views/authentication_views.py:421
226
226
  msgid "password updated successfully"
227
227
  msgstr "le mot de passe a été mis à jour avec succès"
228
228
 
229
- #: views/authentication_views.py:255
229
+ #: views/authentication_views.py:256
230
230
  msgid "Incorrect password"
231
231
  msgstr "Mot de passe incorrect"
232
232
 
233
- #: views/authentication_views.py:258 views/authentication_views.py:429
233
+ #: views/authentication_views.py:259 views/authentication_views.py:430
234
234
  msgid "Empty password is not allowed"
235
235
  msgstr "Un mot de passe vide n’est pas autorisé"
236
236
 
237
- #: views/authentication_views.py:349
237
+ #: views/authentication_views.py:350
238
238
  msgid "User and token are valid"
239
239
  msgstr "L'utilisateur et le token sont valides"
240
240
 
241
- #: views/authentication_views.py:351
241
+ #: views/authentication_views.py:352
242
242
  msgid "User or token is invalid"
243
243
  msgstr "L'utilisateur ou le token est invalide"
244
244
 
245
- #: views/authentication_views.py:463
245
+ #: views/authentication_views.py:464
246
246
  msgid "OTP is already enabled"
247
247
  msgstr "OTP est déjà activé"
248
248
 
249
- #: views/authentication_views.py:504 views/authentication_views.py:540
249
+ #: views/authentication_views.py:505 views/authentication_views.py:541
250
250
  msgid "Invalid code"
251
251
  msgstr "Code invalide"
252
252
 
253
- #: views/authentication_views.py:539
253
+ #: views/authentication_views.py:540
254
254
  msgid "OTP disabled"
255
255
  msgstr "OTP désactivé"
256
256
 
257
- #: views/authentication_views.py:800
257
+ #: views/authentication_views.py:801
258
258
  msgid ""
259
259
  "If the email address you entered is correct, you will receive an email from "
260
260
  "us with instructions to reset your password."
@@ -263,7 +263,7 @@ msgstr ""
263
263
  "un courrier électronique de notre part contenant des instructions pour "
264
264
  "réinitialiser votre mot de passe."
265
265
 
266
- #: views/authentication_views.py:874
266
+ #: views/authentication_views.py:875
267
267
  msgid "A new authentication code has been sent by email."
268
268
  msgstr "Un nouveau code d'authentification a été envoyé par e-mail."
269
269
 
@@ -302,7 +302,7 @@ msgstr "{model} {obj} créé."
302
302
  msgid "{model} {obj} updated."
303
303
  msgstr "{model} {obj} modifié."
304
304
 
305
- #: views/rest_views.py:1269
305
+ #: views/rest_views.py:1276
306
306
  #, python-brace-format
307
307
  msgid "{model} {obj} deleted."
308
308
  msgstr "{model} {obj} supprimé."
@@ -30,6 +30,10 @@ class OtpUserMixin(models.Model):
30
30
  def is_otp(self):
31
31
  return bool(self.otp_secret_token)
32
32
 
33
+ def need_otp_response_extra(self):
34
+ """Add extra attribute to response when need_otp=True."""
35
+ return {}
36
+
33
37
  def enable_otp(self):
34
38
  """Activate OTP for this user.
35
39
 
@@ -184,7 +184,8 @@ class AuthenticationView(
184
184
 
185
185
  Can be overridden to customize the response."""
186
186
  token = self._prepare_token(user, mode, remember_me, otp_login=True)
187
- return JsonResponse(dict(need_otp=True, token=token))
187
+ return JsonResponse(dict(
188
+ need_otp=True, token=token, **user.need_otp_response_extra()))
188
189
 
189
190
  @method_decorator(never_cache)
190
191
  @rest_api(
@@ -958,6 +958,9 @@ class ListRestViewMixin(ModelResponseMixin):
958
958
 
959
959
  def get_navigation_meta(self, obj):
960
960
  qs = self.get_list_queryset()
961
+ if not qs.exists():
962
+ return {}
963
+
961
964
  order = qs.query.order_by
962
965
  qs_window = qs.annotate(
963
966
  prev_id=Window(Lag('id'), order_by=order),
@@ -975,7 +978,11 @@ class ListRestViewMixin(ModelResponseMixin):
975
978
 
976
979
  with connection.cursor() as cursor:
977
980
  cursor.execute(sql, list(params) + [obj.pk])
978
- prev_id, next_id, index = cursor.fetchone() or (None, None)
981
+ row = cursor.fetchone()
982
+ if not row:
983
+ return {}
984
+
985
+ prev_id, next_id, index = row
979
986
  return {
980
987
  'previous_pk': prev_id or qs.last().pk,
981
988
  'next_pk': next_id or qs.first().pk,
@@ -70,9 +70,9 @@ class BasicAPIErrorTest(TestAssertMixin, TestCase):
70
70
  def test_api_error_from_validation_error(self):
71
71
  error = APIError("Default", validation_error=ValidationError(
72
72
  ValidationError("Message")))
73
- self.assertEqual(error.data['message'], "Message")
73
+ self.assertEqual(error.data['message'], "Default\nMessage")
74
74
 
75
75
  # If no general message, default message is used.
76
76
  error = APIError("Default", validation_error=ValidationError(
77
77
  ValidationError(dict(field1="Message"))))
78
- self.assertEqual(error.data['message'], "Default")
78
+ self.assertEqual(error.data['message'], "Default\nfield1: Message")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes