django-pfx 1.7.6.dev11__tar.gz → 1.7.6.dev15__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 (314) hide show
  1. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/PKG-INFO +1 -1
  2. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/SOURCES.txt +1 -0
  4. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/scm_file_list.json +1 -0
  5. django_pfx-1.7.6.dev15/django_pfx.egg-info/scm_version.json +8 -0
  6. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/pfx_views.md +5 -1
  7. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/decorator/rest.py +4 -1
  8. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +4 -4
  9. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/fields.py +14 -6
  10. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/media_rest_view_mixin.py +3 -2
  11. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/migrations/0001_initial.py +1 -1
  12. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/models.py +5 -2
  13. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/basic_api_test.py +42 -0
  14. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_api_doc.py +6 -0
  15. django_pfx-1.7.6.dev15/tests/tests/test_fields_help_text.py +35 -0
  16. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_user_job_api.py +1 -1
  17. django_pfx-1.7.6.dev11/django_pfx.egg-info/scm_version.json +0 -8
  18. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/.gitignore +0 -0
  19. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/.gitlab-ci.yml +0 -0
  20. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/.pre-commit-config.yaml +0 -0
  21. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/LICENSE +0 -0
  22. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/MANIFEST.in +0 -0
  23. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/README.md +0 -0
  24. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/dependency_links.txt +0 -0
  25. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/requires.txt +0 -0
  26. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/django_pfx.egg-info/top_level.txt +0 -0
  27. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/Makefile +0 -0
  28. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/conf.py +0 -0
  29. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/index.rst +0 -0
  30. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/api.views.rst +0 -0
  31. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/authentication.md +0 -0
  32. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/decorator.md +0 -0
  33. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/generate_openapi.md +0 -0
  34. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/getting_started.md +0 -0
  35. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/internationalisation.md +0 -0
  36. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/model.md +0 -0
  37. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/profiling.md +0 -0
  38. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/settings.md +0 -0
  39. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/testing.md +0 -0
  40. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/doc/source/user_jobs.md +0 -0
  41. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/img/pfx.png +0 -0
  42. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/img/pfx.svg +0 -0
  43. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/make_messages +0 -0
  44. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/manage.py +0 -0
  45. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/__init__.py +0 -0
  46. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/__init__.py +0 -0
  47. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/apps.py +0 -0
  48. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/email_backend/__init__.py +0 -0
  49. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/email_backend/q_mailjet_email_backend.py +0 -0
  50. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/exceptions.py +0 -0
  51. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/mailjet/__init__.py +0 -0
  52. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/mailjet/mailjet.py +0 -0
  53. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/mailjet/message_result.py +0 -0
  54. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/migrations/0001_initial.py +0 -0
  55. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/migrations/0002_alter_email_headers.py +0 -0
  56. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/migrations/0003_alter_email_options.py +0 -0
  57. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/migrations/0004_alter_email_mail_from.py +0 -0
  58. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/migrations/__init__.py +0 -0
  59. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/models/__init__.py +0 -0
  60. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/models/email.py +0 -0
  61. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/providers/__init__.py +0 -0
  62. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/providers/email_django_q_executor.py +0 -0
  63. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/shortcuts.py +0 -0
  64. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/tasks.py +0 -0
  65. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/templates/emails/base_template.html +0 -0
  66. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/templates/emails/base_template.txt +0 -0
  67. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/templates/emails/base_template_subject.txt +0 -0
  68. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/urls.py +0 -0
  69. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/views/__init__.py +0 -0
  70. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/emails/views/email_rest_view.py +0 -0
  71. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/__init__.py +0 -0
  72. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/apidoc/__init__.py +0 -0
  73. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/apidoc/parameters.py +0 -0
  74. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/apidoc/schema.py +0 -0
  75. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/apidoc/tags.py +0 -0
  76. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/apps.py +0 -0
  77. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/decorator/__init__.py +0 -0
  78. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/default_settings.py +0 -0
  79. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/exceptions.py +0 -0
  80. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/fields/__init__.py +0 -0
  81. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/fields/decimal_field.py +0 -0
  82. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/fields/media_field.py +0 -0
  83. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  84. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/fields/rich_text_field.py +0 -0
  85. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/http/__init__.py +0 -0
  86. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/http/json_response.py +0 -0
  87. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  88. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/management/__init__.py +0 -0
  89. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/management/commands/__init__.py +0 -0
  90. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  91. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/management/commands/profile.py +0 -0
  92. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/__init__.py +0 -0
  93. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/authenticator.py +0 -0
  94. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/base.py +0 -0
  95. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/email.py +0 -0
  96. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/legacy.py +0 -0
  97. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/mfa/sms.py +0 -0
  98. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/__init__.py +0 -0
  99. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/authentication.py +0 -0
  100. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/locale.py +0 -0
  101. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/profiling.py +0 -0
  102. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/request_too_big_middleware.py +0 -0
  103. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/middleware/ws_cookie_authentication_middleware.py +0 -0
  104. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  105. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  106. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  107. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
  108. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0005_mfadevice_mfadevice_mfa_device_unique_backend.py +0 -0
  109. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0006_alter_pfxuser_managers.py +0 -0
  110. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/0007_alter_pfxuser_options.py +0 -0
  111. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/__init__.py +0 -0
  112. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  113. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  114. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/__init__.py +0 -0
  115. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  116. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/attachment_mixin.py +0 -0
  117. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/cache_mixins.py +0 -0
  118. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/login_ban.py +0 -0
  119. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/mfa_device.py +0 -0
  120. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/mfa_user_mixin.py +0 -0
  121. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/not_null_fields.py +0 -0
  122. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  123. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/pfx_models.py +0 -0
  124. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/pfx_user.py +0 -0
  125. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  126. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/serializers/__init__.py +0 -0
  127. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/serializers/json.py +0 -0
  128. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/settings.py +0 -0
  129. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/shortcuts.py +0 -0
  130. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/sms/__init__.py +0 -0
  131. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/sms/backends/__init__.py +0 -0
  132. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/sms/backends/base.py +0 -0
  133. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/sms/backends/console.py +0 -0
  134. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/storage/__init__.py +0 -0
  135. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/storage/exceptions.py +0 -0
  136. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/storage/local_storage.py +0 -0
  137. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/storage/s3_storage.py +0 -0
  138. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  139. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  140. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  141. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  142. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  143. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  144. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/test.py +0 -0
  145. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/urls.py +0 -0
  146. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/version_check.py +0 -0
  147. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/__init__.py +0 -0
  148. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/authentication_views.py +0 -0
  149. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/filters_views.py +0 -0
  150. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/locale_views.py +0 -0
  151. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/mfa_authentication_views.py +0 -0
  152. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  153. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  154. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  155. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/groups.py +0 -0
  156. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  157. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  158. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  159. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  160. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  161. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  162. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  163. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  164. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  165. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset.py +0 -0
  166. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  167. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  168. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  169. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  170. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  171. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/pfxcore/views/rest_views.py +0 -0
  172. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/settings/__init__.py +0 -0
  173. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/settings/dev.py +0 -0
  174. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/__init__.py +0 -0
  175. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/apps.py +0 -0
  176. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/locale/fr/LC_MESSAGES/django.mo +0 -0
  177. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/locale/fr/LC_MESSAGES/django.po +0 -0
  178. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/0001_initial.py +0 -0
  179. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py +0 -0
  180. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/0003_clean_scheduled_tasks.py +0 -0
  181. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/0004_userjob_summary_url.py +0 -0
  182. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/0005_swappable_user_job.py +0 -0
  183. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/migrations/__init__.py +0 -0
  184. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/models/__init__.py +0 -0
  185. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/models/user_job.py +0 -0
  186. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/models/user_job_attachment.py +0 -0
  187. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/providers/__init__.py +0 -0
  188. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/providers/user_job_django_q_executor.py +0 -0
  189. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/providers/user_job_websocket_channel_provider.py +0 -0
  190. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/tasks.py +0 -0
  191. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/urls.py +0 -0
  192. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/views/__init__.py +0 -0
  193. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/views/user_job_attachment_view.py +0 -0
  194. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/views/user_job_view.py +0 -0
  195. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pfx/userjobs/views/user_websocket_consumer.py +0 -0
  196. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/pyproject.toml +0 -0
  197. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/requirements.txt +0 -0
  198. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/serve-doc +0 -0
  199. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/setup.cfg +0 -0
  200. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/setup.py +0 -0
  201. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/__init__.py +0 -0
  202. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/apps.py +0 -0
  203. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/channel_group_send_calls.py +0 -0
  204. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  205. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/mfa_urls.py +0 -0
  206. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/migrations/__init__.py +0 -0
  207. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/__init__.py +0 -0
  208. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/ci.py +0 -0
  209. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/common.py +0 -0
  210. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/dev.py +0 -0
  211. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/dev_custom_example.py +0 -0
  212. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/settings/dev_default.py +0 -0
  213. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/__init__.py +0 -0
  214. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/basic_api_errors.py +0 -0
  215. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/mfa_test_utils.py +0 -0
  216. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_api_doc_search.py +0 -0
  217. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_auth_api.py +0 -0
  218. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_body_mixin.py +0 -0
  219. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_cache.py +0 -0
  220. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_client.py +0 -0
  221. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_emails_email_api.py +0 -0
  222. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_emails_email_model.py +0 -0
  223. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_emails_q_mailjet_email_backend.py +0 -0
  224. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_emails_send_email_message.py +0 -0
  225. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_choices.py +0 -0
  226. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_date.py +0 -0
  227. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_decimal.py +0 -0
  228. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_minutes_duration.py +0 -0
  229. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_one2many.py +0 -0
  230. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_rich_text.py +0 -0
  231. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_fields_time.py +0 -0
  232. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_filters.py +0 -0
  233. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_locale_api.py +0 -0
  234. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_mfa_legacy.py +0 -0
  235. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_mfa_login_api.py +0 -0
  236. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_mfa_setup_api.py +0 -0
  237. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  238. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_perm_tests.py +0 -0
  239. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_permissions.py +0 -0
  240. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_perms_api.py +0 -0
  241. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_post_migrate_groups_update.py +0 -0
  242. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_profiling_middleware.py +0 -0
  243. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_settings.py +0 -0
  244. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_shortcuts.py +0 -0
  245. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_timezone_middleware.py +0 -0
  246. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_tools.py +0 -0
  247. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_user_job_messages.py +0 -0
  248. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_user_job_model.py +0 -0
  249. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_user_queryset.py +0 -0
  250. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_user_websocket.py +0 -0
  251. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_version_check.py +0 -0
  252. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_view_decorators.py +0 -0
  253. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_view_fields.py +0 -0
  254. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/tests/test_ws_cookie_middleware.py +0 -0
  255. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/urls.py +0 -0
  256. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests/views.py +0 -0
  257. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/__init__.py +0 -0
  258. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/migrations/__init__.py +0 -0
  259. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/__init__.py +0 -0
  260. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/ci.py +0 -0
  261. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/common.py +0 -0
  262. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/dev.py +0 -0
  263. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/dev_custom_example.py +0 -0
  264. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/settings/dev_default.py +0 -0
  265. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/tests/__init__.py +0 -0
  266. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/tests/test_api.py +0 -0
  267. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/tests/test_auth_api.py +0 -0
  268. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/urls.py +0 -0
  269. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_base_user/views.py +0 -0
  270. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/__init__.py +0 -0
  271. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/migrations/0001_initial.py +0 -0
  272. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/migrations/__init__.py +0 -0
  273. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/models.py +0 -0
  274. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/__init__.py +0 -0
  275. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/ci.py +0 -0
  276. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/common.py +0 -0
  277. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/dev.py +0 -0
  278. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/dev_custom_example.py +0 -0
  279. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/settings/dev_default.py +0 -0
  280. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/tests/__init__.py +0 -0
  281. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/tests/test_api.py +0 -0
  282. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/tests/test_auth_api.py +0 -0
  283. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/urls.py +0 -0
  284. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user/views.py +0 -0
  285. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/__init__.py +0 -0
  286. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/migrations/0001_initial.py +0 -0
  287. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/migrations/__init__.py +0 -0
  288. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/models.py +0 -0
  289. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/providers.py +0 -0
  290. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/scope.py +0 -0
  291. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/__init__.py +0 -0
  292. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/ci.py +0 -0
  293. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/common.py +0 -0
  294. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/dev.py +0 -0
  295. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/dev_custom_example.py +0 -0
  296. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/settings/dev_default.py +0 -0
  297. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/tests/__init__.py +0 -0
  298. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/tests/test_user_job.py +0 -0
  299. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_custom_user_job/urls.py +0 -0
  300. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/__init__.py +0 -0
  301. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/migrations/0001_initial.py +0 -0
  302. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/migrations/__init__.py +0 -0
  303. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/models.py +0 -0
  304. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/__init__.py +0 -0
  305. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/ci.py +0 -0
  306. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/common.py +0 -0
  307. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/dev.py +0 -0
  308. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/dev_custom_example.py +0 -0
  309. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/settings/dev_default.py +0 -0
  310. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/tests/__init__.py +0 -0
  311. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/tests/test_api.py +0 -0
  312. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/tests/test_auth_api.py +0 -0
  313. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/urls.py +0 -0
  314. {django_pfx-1.7.6.dev11 → django_pfx-1.7.6.dev15}/tests_user_email_login/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.7.6.dev11
3
+ Version: 1.7.6.dev15
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.7.6.dev11
3
+ Version: 1.7.6.dev15
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
@@ -223,6 +223,7 @@ tests/tests/test_emails_send_email_message.py
223
223
  tests/tests/test_fields_choices.py
224
224
  tests/tests/test_fields_date.py
225
225
  tests/tests/test_fields_decimal.py
226
+ tests/tests/test_fields_help_text.py
226
227
  tests/tests/test_fields_minutes_duration.py
227
228
  tests/tests/test_fields_one2many.py
228
229
  tests/tests/test_fields_rich_text.py
@@ -214,6 +214,7 @@
214
214
  "tests/tests/test_fields_choices.py",
215
215
  "tests/tests/test_fields_date.py",
216
216
  "tests/tests/test_fields_decimal.py",
217
+ "tests/tests/test_fields_help_text.py",
217
218
  "tests/tests/test_fields_minutes_duration.py",
218
219
  "tests/tests/test_fields_one2many.py",
219
220
  "tests/tests/test_fields_rich_text.py",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.7.5",
3
+ "distance": 15,
4
+ "node": "g0ccc5f338cdd3620484d6168dbd4463e12179c94",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-29"
8
+ }
@@ -272,6 +272,10 @@ field = [VF('name')]
272
272
  ```
273
273
  You can specify following optional attributes:
274
274
  * `verbose_name`
275
+ * `help_text`: defaults to the model field `help_text` (or the `help_text`
276
+ argument of `@rest_property`), use an empty string to disable it.
277
+ It is returned by the `/meta` services and used as the field `description`
278
+ in the generated OpenAPI documentation.
275
279
  * `field_type`
276
280
  * `alias`
277
281
  * `readonly`
@@ -286,7 +290,7 @@ Refer to method documentation for details.
286
290
  ### Meta
287
291
 
288
292
  The `ModelResponseMixin` (included in every mixin with a service whose response is a simple object),
289
- exposes a `/meta` service to identify fields (and their characteristics: type, required, readonly, ...),
293
+ exposes a `/meta` service to identify fields (and their characteristics: type, required, readonly, help_text, ...),
290
294
  to enable automatic generation of forms.
291
295
 
292
296
  See the generated API documentation for more details.
@@ -54,9 +54,12 @@ def rest_api(
54
54
  return decorator
55
55
 
56
56
 
57
- def rest_property(string=None, type="CharField", field=None, order=None):
57
+ def rest_property(
58
+ string=None, type="CharField", field=None, order=None,
59
+ help_text=None):
58
60
  def decorator(func):
59
61
  func.short_description = string
62
+ func.help_text = help_text
60
63
  func.field_type = type
61
64
  func.field = field
62
65
  func.order = order
@@ -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-08-12 16:15+0200\n"
10
+ "POT-Creation-Date: 2026-09-24 07:09+0200\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -206,8 +206,8 @@ msgid ""
206
206
  "You’re receiving this email because you requested an authentication code at "
207
207
  "%(site_name)s."
208
208
  msgstr ""
209
- "Vous recevez cet e-mail parce que vous avez demandé un code d’authentification "
210
- "sur %(site_name)s."
209
+ "Vous recevez cet e-mail parce que vous avez demandé un code "
210
+ "d’authentification sur %(site_name)s."
211
211
 
212
212
  #: templates/registration/otp_code_email.txt:4
213
213
  msgid "Authentication code:"
@@ -323,7 +323,7 @@ msgstr ""
323
323
  msgid "Invalid value for {filter} filter"
324
324
  msgstr "Valeur invalide pour le filtre {filter}"
325
325
 
326
- #: views/media_rest_view_mixin.py:37 views/media_rest_view_mixin.py:125
326
+ #: views/media_rest_view_mixin.py:38 views/media_rest_view_mixin.py:126
327
327
  msgid "Unexpected storage error"
328
328
  msgstr "Erreur de stockage inattendue"
329
329
 
@@ -123,12 +123,13 @@ class ViewField:
123
123
  choices=None, json_repr=None, media_field_api=None,
124
124
  related_model=None, related_model_api=None, related_fields=None,
125
125
  related_filter=None,
126
- select_related=None, prefetch_related=None):
126
+ select_related=None, prefetch_related=None, help_text=None):
127
127
  self.name = name
128
128
  self.alias = alias or name
129
129
  self.readonly_create = readonly or readonly_create
130
130
  self.readonly_update = readonly or readonly_update
131
131
  self.verbose_name = verbose_name or name
132
+ self.help_text = help_text
132
133
  self.field_type = field_type
133
134
  self.db_type = db_type
134
135
  self.order = order
@@ -151,7 +152,8 @@ class ViewField:
151
152
 
152
153
  def meta(self):
153
154
  res = dict(
154
- type=self.field_type, db_type=self.db_type, name=self.verbose_name)
155
+ type=self.field_type, db_type=self.db_type, name=self.verbose_name,
156
+ help_text=self.help_text and str(self.help_text) or None)
155
157
  if self.choices:
156
158
  res['choices'] = [
157
159
  dict(label=str(v), value=k) for k, v in self.choices.items()]
@@ -242,14 +244,17 @@ class ViewField:
242
244
  return cls.from_model_field(name, field, **kwargs)
243
245
  verbose_name = getattr(
244
246
  prop.fget, 'short_description', prop.fget.__name__)
247
+ help_text = getattr(prop.fget, 'help_text', None)
245
248
  field_type = getattr(prop.fget, 'field_type', None)
246
249
  db_type = getattr(prop.fget, 'db_type', None)
247
250
  else:
248
251
  verbose_name = (
249
252
  hasattr(prop, 'name') and prop.name or str(prop))
253
+ help_text = None
250
254
  field_type = None
251
255
  db_type = None
252
256
  setifnone(kwargs, 'verbose_name', verbose_name)
257
+ setifnone(kwargs, 'help_text', help_text)
253
258
  setifnone(kwargs, 'field_type', field_type)
254
259
  setifnone(kwargs, 'db_type', db_type)
255
260
  return ViewField(name, **kwargs)
@@ -257,6 +262,7 @@ class ViewField:
257
262
  @classmethod
258
263
  def from_model_field(cls, name, field, **kwargs):
259
264
  setifnone(kwargs, 'verbose_name', cls._get_model_verbose_name(field))
265
+ setifnone(kwargs, 'help_text', getattr(field, 'help_text', None))
260
266
  setifnone(
261
267
  kwargs, 'field_type', FieldType.from_model_field(field.__class__))
262
268
  setifnone(
@@ -343,7 +349,7 @@ class ViewField:
343
349
  else:
344
350
  res['properties'] = properties
345
351
  elif self.field_type == FieldType.MinutesDurationField:
346
- res = pfx_fields.MinutesDurationField.schema
352
+ res = dict(pfx_fields.MinutesDurationField.schema)
347
353
  elif self.field_type == FieldType.ModelObjectList:
348
354
  res['items'] = dict(type='object')
349
355
  properties = {}
@@ -378,6 +384,8 @@ class ViewField:
378
384
  res['readonly'] = self.readonly_create and self.readonly_update
379
385
  if self.choices:
380
386
  res['enum'] = list(self.choices)
387
+ if self.help_text:
388
+ res['description'] = str(self.help_text)
381
389
  return res
382
390
 
383
391
 
@@ -481,10 +489,10 @@ class VF:
481
489
  choices=None, select_related=None, prefetch_related=None,
482
490
  json_repr=None, related_model=None, related_model_api=None,
483
491
  field=None, related_fields=None, related_filter=None,
484
- media_field_api=None, db_type=None, order=None):
492
+ media_field_api=None, db_type=None, order=None, help_text=None):
485
493
  self.kwargs = dict(
486
- name=name, verbose_name=verbose_name, field_type=field_type,
487
- alias=alias,
494
+ name=name, verbose_name=verbose_name, help_text=help_text,
495
+ field_type=field_type, alias=alias,
488
496
  readonly=readonly, readonly_create=readonly_create,
489
497
  readonly_update=readonly_update, choices=choices,
490
498
  select_related=select_related, prefetch_related=prefetch_related,
@@ -3,6 +3,7 @@ import logging
3
3
  from django.core.exceptions import FieldDoesNotExist
4
4
  from django.http import FileResponse, HttpResponse
5
5
  from django.shortcuts import redirect
6
+ from django.utils.http import content_disposition_header
6
7
  from django.utils.translation import gettext_lazy as _
7
8
 
8
9
  from pfx.pfxcore.decorator import rest_api
@@ -42,8 +43,8 @@ def get_media_field_response(obj, field, request):
42
43
  inline = get_bool(request.GET, "inline")
43
44
  if settings.STORAGE_LOCAL_X_ACCEL_REDIRECT:
44
45
  response = HttpResponse()
45
- response["Content-Disposition"] = (
46
- f"{"inline" if inline else "attachment"}; filename={filename}")
46
+ response["Content-Disposition"] = content_disposition_header(
47
+ not inline, filename)
47
48
  response["Content-Type"] = attr.get('content-type', '')
48
49
  response['X-Accel-Redirect'] = (
49
50
  f"/filestore/{attr.get('key')}")
@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
40
40
  ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
41
41
  ('first_name', models.CharField(max_length=30, verbose_name='First Name')),
42
42
  ('last_name', models.CharField(max_length=30, verbose_name='Last Name')),
43
- ('slug', models.SlugField(unique=True, verbose_name='Slug')),
43
+ ('slug', models.SlugField(help_text='Unique identifier used in URLs', unique=True, verbose_name='Slug')),
44
44
  ('gender', models.CharField(choices=[('male', 'Male'), ('female', 'Female')], default='male', max_length=10, verbose_name='Gender')),
45
45
  ('science_fiction', models.BooleanField(default=False, verbose_name='Science Fiction')),
46
46
  ('created_at', models.DateField(auto_now_add=True, verbose_name='Created at')),
@@ -56,7 +56,8 @@ class Author(CacheableMixin, JSONReprMixin, models.Model):
56
56
 
57
57
  first_name = models.CharField(_("First Name"), max_length=30)
58
58
  last_name = models.CharField(_("Last Name"), max_length=30)
59
- slug = models.SlugField("Slug", unique=True)
59
+ slug = models.SlugField(
60
+ "Slug", unique=True, help_text="Unique identifier used in URLs")
60
61
  gender = models.CharField("Gender", max_length=10, choices=[
61
62
  ('male', "Male"), ('female', "Female")], default='male')
62
63
  science_fiction = models.BooleanField("Science Fiction", default=False)
@@ -83,7 +84,9 @@ class Author(CacheableMixin, JSONReprMixin, models.Model):
83
84
  def __str__(self):
84
85
  return f"{self.first_name} {self.last_name}"
85
86
 
86
- @rest_property("Name Length", "IntegerField")
87
+ @rest_property(
88
+ "Name Length", "IntegerField",
89
+ help_text="Length of the author's full name")
87
90
  def name_length(self):
88
91
  return len(str(self))
89
92
 
@@ -596,6 +596,13 @@ class BasicAPITest(TestAssertMixin, TestCase):
596
596
  self.assertJE(response, 'fields.name_length.name', 'Name Length')
597
597
  self.assertJE(response, 'fields.types.type', 'ModelObjectList')
598
598
  self.assertJE(response, 'fields.types.name', 'Types')
599
+ self.assertJE(response, 'fields.first_name.help_text', None)
600
+ self.assertJE(
601
+ response, 'fields.slug.help_text',
602
+ 'Unique identifier used in URLs')
603
+ self.assertJE(
604
+ response, 'fields.name_length.help_text',
605
+ "Length of the author's full name")
599
606
  response = self.client.get('/api/books/meta')
600
607
  self.assertJE(response, 'fields.author.type', 'ModelObject')
601
608
  self.assertJE(response, 'fields.author.model', 'tests.Author')
@@ -840,6 +847,41 @@ class BasicAPITest(TestAssertMixin, TestCase):
840
847
  self.assertJE(response, 'local_file', None)
841
848
  self.assertFalse(Path(f'/tmp/django-pfx-filestore/{key2}').exists())
842
849
 
850
+ def test_get_file_content_disposition(self):
851
+ """The file name must survive both local serving paths.
852
+
853
+ The name holds "…", outside latin-1: written by hand into the
854
+ X-Accel header, it made Django MIME-encode the whole value
855
+ (`=?utf-8?q?…?=`), which browsers cannot read, so "inline" was
856
+ lost. The ";" would also have cut the unquoted name short.
857
+ FileResponse is checked too, as both paths must agree.
858
+ """
859
+ response = self.client.post('/api/books', dict(
860
+ name="Test Book",
861
+ author=self.author1.pk,
862
+ pub_date='2000-01-01',
863
+ local_file=dict(
864
+ name='Crédit; école[…].txt',
865
+ base64='data:text/plain;charset=utf-8;'
866
+ 'base64,VGVzdCBjb250ZW50')))
867
+ self.assertRC(response, 200)
868
+ url = f"/api/books/{self.get_val(response, 'pk')}/local_file"
869
+ name = (
870
+ "filename*=utf-8''"
871
+ "Cr%C3%A9dit%3B%20%C3%A9cole%5B%E2%80%A6%5D.txt")
872
+
873
+ for x_accel in (True, False):
874
+ with override_settings(STORAGE_LOCAL_X_ACCEL_REDIRECT=x_accel):
875
+ response = self.client.get(url)
876
+ self.assertRC(response, 200)
877
+ self.assertEqual(
878
+ response['Content-Disposition'], f"attachment; {name}")
879
+
880
+ response = self.client.get(f"{url}?inline=true")
881
+ self.assertRC(response, 200)
882
+ self.assertEqual(
883
+ response['Content-Disposition'], f"inline; {name}")
884
+
843
885
  def test_create_null_values(self):
844
886
  response = self.client.post(
845
887
  '/api/books', dict(
@@ -209,9 +209,15 @@ class ApiDocTest(TestAssertMixin, TestCase):
209
209
  self.assertIn("Author", schema_key)
210
210
  props = spec['components']['schemas'][schema_key]['properties']
211
211
  self.assertJE(props, 'first_name.type', 'string')
212
+ self.assertJENotExists(props, 'first_name.description')
213
+ self.assertJE(
214
+ props, 'slug.description', 'Unique identifier used in URLs')
212
215
  # Check an @rest_property field (readonly)
213
216
  self.assertJE(props, 'name_length.type', 'number')
214
217
  self.assertJE(props, 'name_length.readonly', True)
218
+ self.assertJE(
219
+ props, 'name_length.description',
220
+ "Length of the author's full name")
215
221
  self.assertJE(props, 'gender.type', 'string')
216
222
  self.assertJE(props, 'gender.enum', ['male', 'female'])
217
223
  self.assertJE(props, 'types.type', 'array')
@@ -0,0 +1,35 @@
1
+ from django.test import TestCase
2
+
3
+ from pfx.pfxcore.views.fields import VF, process_fields
4
+ from tests.models import Author
5
+
6
+
7
+ class FieldsHelpTextTest(TestCase):
8
+
9
+ def test_help_text_from_model(self):
10
+ fields = process_fields(Author, ['first_name', 'slug', 'name_length'])
11
+ self.assertIsNone(fields['first_name'].meta()['help_text'])
12
+ self.assertEqual(
13
+ fields['slug'].meta()['help_text'],
14
+ "Unique identifier used in URLs")
15
+ self.assertEqual(
16
+ fields['name_length'].meta()['help_text'],
17
+ "Length of the author's full name")
18
+
19
+ def test_help_text_override(self):
20
+ fields = process_fields(Author, [
21
+ VF('first_name', help_text="Custom first name help"),
22
+ VF('slug', help_text="Custom slug help"),
23
+ VF('name_length', help_text="Custom length help")])
24
+ self.assertEqual(
25
+ fields['first_name'].meta()['help_text'], "Custom first name help")
26
+ self.assertEqual(
27
+ fields['slug'].meta()['help_text'], "Custom slug help")
28
+ self.assertEqual(
29
+ fields['name_length'].meta()['help_text'], "Custom length help")
30
+
31
+ def test_help_text_disable(self):
32
+ fields = process_fields(Author, [
33
+ VF('slug', help_text=''), VF('name_length', help_text='')])
34
+ self.assertIsNone(fields['slug'].meta()['help_text'])
35
+ self.assertIsNone(fields['name_length'].meta()['help_text'])
@@ -353,7 +353,7 @@ class TestUserJobApi(TestAssertMixin, TestCase):
353
353
  self.assertRC(response, 200)
354
354
  self.assertEqual(
355
355
  response.headers['Content-Disposition'],
356
- "attachment; filename=test.txt")
356
+ 'attachment; filename="test.txt"')
357
357
  self.assertEqual(
358
358
  response.headers['X-Accel-Redirect'],
359
359
  f"/filestore/{att.file['key']}")
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "1.7.5",
3
- "distance": 11,
4
- "node": "g113691e9ec664f316585c0c5af016df1001e5e02",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-09-01"
8
- }