django-pfx 1.7.3.dev8__tar.gz → 1.7.3.dev12__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 (261) hide show
  1. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/PKG-INFO +1 -1
  2. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/django_pfx.egg-info/SOURCES.txt +2 -0
  4. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/middleware/__init__.py +1 -0
  5. django_pfx-1.7.3.dev12/pfx/pfxcore/middleware/request_too_big_middleware.py +25 -0
  6. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/storage/local_storage.py +1 -1
  7. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/storage/s3_storage.py +4 -4
  8. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/locale/fr/LC_MESSAGES/django.po +3 -3
  9. django_pfx-1.7.3.dev12/tests/migrations/0007_attachment.py +27 -0
  10. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/models.py +10 -0
  11. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/basic_api_test.py +27 -0
  12. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_emails_email_api.py +20 -0
  13. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_emails_send_email_message.py +13 -1
  14. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/.gitignore +0 -0
  15. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/.gitlab-ci.yml +0 -0
  16. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/.pre-commit-config.yaml +0 -0
  17. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/LICENSE +0 -0
  18. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/MANIFEST.in +0 -0
  19. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/README.md +0 -0
  20. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/django_pfx.egg-info/dependency_links.txt +0 -0
  21. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/django_pfx.egg-info/requires.txt +0 -0
  22. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/django_pfx.egg-info/top_level.txt +0 -0
  23. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/Makefile +0 -0
  24. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/conf.py +0 -0
  25. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/index.rst +0 -0
  26. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/api.views.rst +0 -0
  27. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/authentication.md +0 -0
  28. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/decorator.md +0 -0
  29. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/generate_openapi.md +0 -0
  30. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/getting_started.md +0 -0
  31. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/internationalisation.md +0 -0
  32. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/model.md +0 -0
  33. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/pfx_views.md +0 -0
  34. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/profiling.md +0 -0
  35. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/settings.md +0 -0
  36. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/doc/source/testing.md +0 -0
  37. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/img/pfx.png +0 -0
  38. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/img/pfx.svg +0 -0
  39. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/make_messages +0 -0
  40. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/manage.py +0 -0
  41. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/__init__.py +0 -0
  42. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/__init__.py +0 -0
  43. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/apps.py +0 -0
  44. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/email_backend/__init__.py +0 -0
  45. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/email_backend/q_mailjet_email_backend.py +0 -0
  46. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/exceptions.py +0 -0
  47. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/mailjet/__init__.py +0 -0
  48. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/mailjet/mailjet.py +0 -0
  49. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/mailjet/message_result.py +0 -0
  50. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/migrations/0001_initial.py +0 -0
  51. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/migrations/0002_alter_email_headers.py +0 -0
  52. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/migrations/0003_alter_email_options.py +0 -0
  53. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/migrations/__init__.py +0 -0
  54. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/models/__init__.py +0 -0
  55. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/models/email.py +0 -0
  56. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/providers/__init__.py +0 -0
  57. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/providers/email_django_q_executor.py +0 -0
  58. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/shortcuts.py +0 -0
  59. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/tasks.py +0 -0
  60. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/templates/emails/base_template.html +0 -0
  61. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/templates/emails/base_template.txt +0 -0
  62. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/templates/emails/base_template_subject.txt +0 -0
  63. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/urls.py +0 -0
  64. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/views/__init__.py +0 -0
  65. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/emails/views/email_rest_view.py +0 -0
  66. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/__init__.py +0 -0
  67. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/apidoc/__init__.py +0 -0
  68. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/apidoc/parameters.py +0 -0
  69. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/apidoc/schema.py +0 -0
  70. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/apidoc/tags.py +0 -0
  71. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/apps.py +0 -0
  72. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/decorator/__init__.py +0 -0
  73. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/decorator/rest.py +0 -0
  74. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/default_settings.py +0 -0
  75. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/exceptions.py +0 -0
  76. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/fields/__init__.py +0 -0
  77. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/fields/decimal_field.py +0 -0
  78. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/fields/media_field.py +0 -0
  79. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  80. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/fields/rich_text_field.py +0 -0
  81. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/http/__init__.py +0 -0
  82. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/http/json_response.py +0 -0
  83. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  84. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +0 -0
  85. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/management/__init__.py +0 -0
  86. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/management/commands/__init__.py +0 -0
  87. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  88. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/management/commands/profile.py +0 -0
  89. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/middleware/authentication.py +0 -0
  90. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/middleware/locale.py +0 -0
  91. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/middleware/profiling.py +0 -0
  92. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  93. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  94. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  95. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
  96. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/__init__.py +0 -0
  97. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  98. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  99. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/__init__.py +0 -0
  100. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  101. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/attachment_mixin.py +0 -0
  102. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/cache_mixins.py +0 -0
  103. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/login_ban.py +0 -0
  104. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/mfa_user_mixin.py +0 -0
  105. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/not_null_fields.py +0 -0
  106. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  107. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/pfx_models.py +0 -0
  108. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/pfx_user.py +0 -0
  109. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  110. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/serializers/__init__.py +0 -0
  111. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/serializers/json.py +0 -0
  112. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/settings.py +0 -0
  113. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/shortcuts.py +0 -0
  114. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/sms/__init__.py +0 -0
  115. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/sms/backends/__init__.py +0 -0
  116. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/sms/backends/base.py +0 -0
  117. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/sms/backends/console.py +0 -0
  118. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/storage/__init__.py +0 -0
  119. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/storage/exceptions.py +0 -0
  120. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  121. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  122. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  123. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  124. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  125. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  126. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/test.py +0 -0
  127. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/urls.py +0 -0
  128. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/__init__.py +0 -0
  129. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/authentication_views.py +0 -0
  130. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/fields.py +0 -0
  131. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/filters_views.py +0 -0
  132. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/locale_views.py +0 -0
  133. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
  134. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  135. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  136. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  137. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/groups.py +0 -0
  138. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  139. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  140. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  141. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  142. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  143. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  144. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  145. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  146. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  147. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset.py +0 -0
  148. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  149. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  150. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  151. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  152. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  153. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/pfxcore/views/rest_views.py +0 -0
  154. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/settings/__init__.py +0 -0
  155. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/settings/dev.py +0 -0
  156. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/__init__.py +0 -0
  157. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/apps.py +0 -0
  158. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/locale/fr/LC_MESSAGES/django.mo +0 -0
  159. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/locale/fr/LC_MESSAGES/django.po +0 -0
  160. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/migrations/0001_initial.py +0 -0
  161. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py +0 -0
  162. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/migrations/__init__.py +0 -0
  163. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/models/__init__.py +0 -0
  164. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/models/user_job.py +0 -0
  165. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/models/user_job_attachment.py +0 -0
  166. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/providers/__init__.py +0 -0
  167. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/providers/user_job_django_q_executor.py +0 -0
  168. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/providers/user_job_websocket_channel_provider.py +0 -0
  169. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/tasks.py +0 -0
  170. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/urls.py +0 -0
  171. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/views/__init__.py +0 -0
  172. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/views/user_job_attachment_view.py +0 -0
  173. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/views/user_job_view.py +0 -0
  174. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pfx/userjobs/views/user_websocket_consumer.py +0 -0
  175. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/pyproject.toml +0 -0
  176. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/requirements.txt +0 -0
  177. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/serve-doc +0 -0
  178. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/setup.cfg +0 -0
  179. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/setup.py +0 -0
  180. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/__init__.py +0 -0
  181. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/apps.py +0 -0
  182. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/channel_group_send_calls.py +0 -0
  183. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0001_initial.py +0 -0
  184. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0002_alter_book_cover.py +0 -0
  185. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0003_book_local_file.py +0 -0
  186. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0004_mfausermixin_fields.py +0 -0
  187. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0005_mfausermixin_fields_fix.py +0 -0
  188. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/0006_rename_otp_enabled_user_mfa_authenticator_enabled_and_more.py +0 -0
  189. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/migrations/__init__.py +0 -0
  190. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/__init__.py +0 -0
  191. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/ci.py +0 -0
  192. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/common.py +0 -0
  193. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/dev.py +0 -0
  194. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/dev_custom_example.py +0 -0
  195. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/settings/dev_default.py +0 -0
  196. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/__init__.py +0 -0
  197. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/basic_api_errors.py +0 -0
  198. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_api_doc.py +0 -0
  199. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_api_doc_search.py +0 -0
  200. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_auth_api.py +0 -0
  201. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_body_mixin.py +0 -0
  202. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_cache.py +0 -0
  203. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_client.py +0 -0
  204. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_emails_email_model.py +0 -0
  205. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_emails_q_mailjet_email_backend.py +0 -0
  206. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_choices.py +0 -0
  207. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_date.py +0 -0
  208. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_decimal.py +0 -0
  209. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_minutes_duration.py +0 -0
  210. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_one2many.py +0 -0
  211. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_rich_text.py +0 -0
  212. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_fields_time.py +0 -0
  213. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_filters.py +0 -0
  214. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_locale_api.py +0 -0
  215. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  216. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_perm_tests.py +0 -0
  217. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_permissions.py +0 -0
  218. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_perms_api.py +0 -0
  219. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_post_migrate_groups_update.py +0 -0
  220. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_profiling_middleware.py +0 -0
  221. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_settings.py +0 -0
  222. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_shortcuts.py +0 -0
  223. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_timezone_middleware.py +0 -0
  224. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_tools.py +0 -0
  225. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_user_job_api.py +0 -0
  226. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_user_job_messages.py +0 -0
  227. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_user_job_model.py +0 -0
  228. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_user_queryset.py +0 -0
  229. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_view_decorators.py +0 -0
  230. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/tests/test_view_fields.py +0 -0
  231. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/urls.py +0 -0
  232. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests/views.py +0 -0
  233. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/__init__.py +0 -0
  234. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/migrations/0001_initial.py +0 -0
  235. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/migrations/__init__.py +0 -0
  236. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/__init__.py +0 -0
  237. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/ci.py +0 -0
  238. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/common.py +0 -0
  239. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/dev.py +0 -0
  240. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/dev_custom_example.py +0 -0
  241. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/settings/dev_default.py +0 -0
  242. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/tests/__init__.py +0 -0
  243. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/tests/test_api.py +0 -0
  244. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/tests/test_auth_api.py +0 -0
  245. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/urls.py +0 -0
  246. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_base_user/views.py +0 -0
  247. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/__init__.py +0 -0
  248. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/migrations/0001_initial.py +0 -0
  249. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/migrations/__init__.py +0 -0
  250. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/models.py +0 -0
  251. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/__init__.py +0 -0
  252. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/ci.py +0 -0
  253. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/common.py +0 -0
  254. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/dev.py +0 -0
  255. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/dev_custom_example.py +0 -0
  256. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/settings/dev_default.py +0 -0
  257. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/tests/__init__.py +0 -0
  258. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/tests/test_api.py +0 -0
  259. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/tests/test_auth_api.py +0 -0
  260. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/tests_custom_user/urls.py +0 -0
  261. {django_pfx-1.7.3.dev8 → django_pfx-1.7.3.dev12}/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.7.3.dev8
3
+ Version: 1.7.3.dev12
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.3.dev8
3
+ Version: 1.7.3.dev12
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
@@ -88,6 +88,7 @@ pfx/pfxcore/middleware/__init__.py
88
88
  pfx/pfxcore/middleware/authentication.py
89
89
  pfx/pfxcore/middleware/locale.py
90
90
  pfx/pfxcore/middleware/profiling.py
91
+ pfx/pfxcore/middleware/request_too_big_middleware.py
91
92
  pfx/pfxcore/migrations/0001_initial.py
92
93
  pfx/pfxcore/migrations/0002_pfxpermissionsuser.py
93
94
  pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py
@@ -182,6 +183,7 @@ tests/migrations/0003_book_local_file.py
182
183
  tests/migrations/0004_mfausermixin_fields.py
183
184
  tests/migrations/0005_mfausermixin_fields_fix.py
184
185
  tests/migrations/0006_rename_otp_enabled_user_mfa_authenticator_enabled_and_more.py
186
+ tests/migrations/0007_attachment.py
185
187
  tests/migrations/__init__.py
186
188
  tests/settings/__init__.py
187
189
  tests/settings/ci.py
@@ -4,3 +4,4 @@ from .authentication import (
4
4
  )
5
5
  from .locale import LocaleMiddleware
6
6
  from .profiling import ProfilingDatabaseRouter, ProfilingMiddleware
7
+ from .request_too_big_middleware import RequestTooBigMiddleware
@@ -0,0 +1,25 @@
1
+ from django.conf import settings
2
+ from django.core.exceptions import RequestDataTooBig
3
+ from django.http import HttpResponse
4
+
5
+
6
+ class RequestTooBigMiddleware:
7
+ """Dev middleware to simulate 413 from HTTP reverse proxy.
8
+ Don't use it in production,
9
+ set DATA_UPLOAD_MAX_MEMORY_SIZE > reverse proxy limit.
10
+ """
11
+ def __init__(self, get_response):
12
+ self.get_response = get_response
13
+
14
+ def __call__(self, request):
15
+ try:
16
+ # force body reading to catch RequestDataTooBig early
17
+ _ = request.body
18
+ except RequestDataTooBig:
19
+ response = HttpResponse("Request Entity Too Large", status=413)
20
+ # In dev, UI and API are on different ports,
21
+ # so we need CORS headers.
22
+ response["Access-Control-Allow-Origin"] = settings.PFX_BASE_URL
23
+ response["Access-Control-Allow-Credentials"] = "true"
24
+ return response
25
+ return self.get_response(request)
@@ -39,7 +39,7 @@ class LocalStorage:
39
39
  }
40
40
 
41
41
  def delete(self, value):
42
- if not value or 'key' not in value:
42
+ if not value or not value.get('key'):
43
43
  return value # pragma: no cover
44
44
  path = Path(settings.STORAGE_LOCAL_ROOT, value['key'])
45
45
  path.unlink(missing_ok=True)
@@ -23,8 +23,8 @@ class S3Storage:
23
23
  endpoint_url=settings.STORAGE_S3_AWS_ENDPOINT_URL)
24
24
 
25
25
  def to_python(self, value):
26
- if 'key' not in value:
27
- return value # pragma: no cover
26
+ if not value or not value.get('key'):
27
+ return None
28
28
  try:
29
29
  response = self.s3_client().head_object(
30
30
  Bucket=settings.STORAGE_S3_AWS_S3_BUCKET, Key=value['key'])
@@ -72,8 +72,8 @@ class S3Storage:
72
72
  return dict(key=key)
73
73
 
74
74
  def delete(self, value):
75
- if 'key' not in value:
76
- return value # pragma: no cover
75
+ if not value or not value.get('key'):
76
+ return
77
77
  try:
78
78
  self.s3_client().delete_object(
79
79
  Bucket=settings.STORAGE_S3_AWS_S3_BUCKET, Key=value['key'])
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2025-04-08 13:56+0200\n"
11
+ "POT-Creation-Date: 2026-06-02 17:01+0200\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,11 +18,11 @@ msgstr ""
18
18
  "Content-Transfer-Encoding: 8bit\n"
19
19
  "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20
20
 
21
- #: models.py:69
21
+ #: models.py:70
22
22
  msgid "First Name"
23
23
  msgstr "Prénom"
24
24
 
25
- #: models.py:70
25
+ #: models.py:71
26
26
  msgid "Last Name"
27
27
  msgstr "Nom"
28
28
 
@@ -0,0 +1,27 @@
1
+ # Generated by Django 4.2.30 on 2026-06-02 14:41
2
+ # flake8: noqa
3
+
4
+ from django.db import migrations, models
5
+
6
+ import pfx.pfxcore.fields.media_field
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ('tests', '0006_rename_otp_enabled_user_mfa_authenticator_enabled_and_more'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='Attachment',
18
+ fields=[
19
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+ ('file', pfx.pfxcore.fields.media_field.MediaField(blank=True, max_length=255, null=True, validators=[pfx.pfxcore.fields.media_field.validate_media_json], verbose_name='File')),
21
+ ],
22
+ options={
23
+ 'verbose_name': 'Attachment',
24
+ 'verbose_name_plural': 'Attachments',
25
+ },
26
+ ),
27
+ ]
@@ -8,6 +8,7 @@ from pfx.pfxcore.decorator import rest_property
8
8
  from pfx.pfxcore.fields import MediaField, MinutesDurationField
9
9
  from pfx.pfxcore.models import (
10
10
  AbstractPFXUser,
11
+ AttachmentMixin,
11
12
  CacheableMixin,
12
13
  CacheDependsMixin,
13
14
  JSONReprMixin,
@@ -172,3 +173,12 @@ class Book(CacheDependsMixin, PFXModelMixin, models.Model):
172
173
  type: string
173
174
  """
174
175
  return super().json_repr(author_name=str(self.author), **values)
176
+
177
+
178
+ class Attachment(AttachmentMixin, models.Model):
179
+ class Meta:
180
+ verbose_name = "Attachment"
181
+ verbose_name_plural = "Attachments"
182
+
183
+ def get_file_key(self, filename):
184
+ return f"attachments/{self.pk}/{filename}"
@@ -2,6 +2,7 @@ from datetime import date
2
2
  from pathlib import Path
3
3
  from unittest.mock import MagicMock, patch
4
4
 
5
+ from django.conf import settings
5
6
  from django.db import connection
6
7
  from django.test import TestCase, override_settings
7
8
 
@@ -959,6 +960,32 @@ class BasicAPITest(TestAssertMixin, TestCase):
959
960
  self.assertJE(
960
961
  response, 'gender.@0', "Value 'writer' is not a valid choice.")
961
962
 
963
+ @override_settings(
964
+ STORAGE_S3_AWS_REGION="fake-region",
965
+ STORAGE_S3_AWS_ACCESS_KEY="FAKE",
966
+ STORAGE_S3_AWS_SECRET_KEY="FAKE-SECRET",
967
+ STORAGE_S3_AWS_S3_BUCKET="dragonfly.fake",
968
+ STORAGE_S3_AWS_GET_URL_EXPIRE=300,
969
+ STORAGE_S3_AWS_PUT_URL_EXPIRE=300)
970
+ def test_update_null_file(self):
971
+ """Empty keys will return None through API, then ensure we can
972
+ save with None as file."""
973
+ Path(settings.STORAGE_LOCAL_ROOT).mkdir(parents=True, exist_ok=True)
974
+
975
+ self.author1_book1.cover = dict(key="")
976
+ self.author1_book1.local_file = dict(key="")
977
+ self.author1_book1.save()
978
+
979
+ with self.captureOnCommitCallbacks(execute=True):
980
+ response = self.client.put(
981
+ f'/api/books/{self.author1_book1.pk}', dict(
982
+ name="The Hobbit, Deluxe Edition",
983
+ local_file=None,
984
+ cover=None))
985
+ self.assertRC(response, 200)
986
+ self.assertJE(response, 'cover', None)
987
+ self.assertJE(response, 'local_file', None)
988
+
962
989
  def test_empty_number_fields(self):
963
990
  response = self.client.post(
964
991
  '/api/books', {
@@ -24,6 +24,13 @@ class TestEmailsEmailApi(TestAssertMixin, TestCase):
24
24
 
25
25
  @classmethod
26
26
  def setUpTestData(cls):
27
+ cls.superuser = User.objects.create_user(
28
+ username='admin',
29
+ email="admin@example.org",
30
+ first_name='Admin',
31
+ last_name='User',
32
+ password='test',
33
+ is_superuser=True)
27
34
  cls.user = User.objects.create_user(
28
35
  username='jrr.tolkien',
29
36
  email="jrr.tolkien@oxford.com",
@@ -84,3 +91,16 @@ class TestEmailsEmailApi(TestAssertMixin, TestCase):
84
91
  response = self.client.get(f'/api/emails/emails/{m.pk}')
85
92
  self.assertRC(response, 200)
86
93
  self.assertJE(response, 'status.value', 'to_send')
94
+
95
+ @override_settings(PFX_EMAILS_USER_ACCESS='all')
96
+ @responses.activate
97
+ def test_delete(self):
98
+ m = self.create_mail()
99
+
100
+ self.client.login(username=self.user.username)
101
+ response = self.client.delete(f'/api/emails/emails/{m.pk}')
102
+ self.assertRC(response, 403)
103
+
104
+ self.client.login(username=self.superuser.username)
105
+ response = self.client.delete(f'/api/emails/emails/{m.pk}')
106
+ self.assertRC(response, 200)
@@ -5,7 +5,9 @@ from django.core import mail
5
5
  from django.test import TestCase, override_settings
6
6
 
7
7
  from pfx.emails.shortcuts import send_email_message
8
+ from pfx.pfxcore.storage import LocalStorage
8
9
  from pfx.pfxcore.test import APIClient, TestAssertMixin
10
+ from tests.models import Attachment
9
11
 
10
12
  logger = logging.getLogger(__name__)
11
13
 
@@ -15,6 +17,7 @@ logger = logging.getLogger(__name__)
15
17
  PFX_BASE_URL='http://example.org',
16
18
  PFX_EMAILS_LOGO_URL='http://example.org/logo.png',
17
19
  PFX_EMAILS_DEFAULT_SIGNATURE='PFX, a DJango rest framework',
20
+ STORAGE_LOCAL_ROOT='/tmp/django-pfx-filestore',
18
21
  MAIL_WHITELIST_ACTIVE=True,
19
22
  MAIL_WHITELIST_EMAILS=[],
20
23
  MAIL_WHITELIST_DOMAINS=[])
@@ -23,9 +26,15 @@ class TestEmailsSendEmailMessage(TestAssertMixin, TestCase):
23
26
  self.client = APIClient(with_cookie=True)
24
27
 
25
28
  def test_send_email_message(self):
29
+ Attachment._meta.get_field('file').storage = LocalStorage()
30
+ att = Attachment.objects.create()
31
+ att.file = Attachment._meta.get_field('file').upload(
32
+ att, b"A test file content.", "test.txt")
33
+ att.save()
34
+
26
35
  send_email_message(
27
36
  'test@example.org', 'base_template',
28
- data={'subject': "Test message"})
37
+ data={'subject': "Test message"}, attachments=[att])
29
38
 
30
39
  # Test first message
31
40
  m = mail.outbox[0]
@@ -40,6 +49,9 @@ class TestEmailsSendEmailMessage(TestAssertMixin, TestCase):
40
49
  self.assertIn(
41
50
  'PFX, a DJango rest framework', txt_msg)
42
51
 
52
+ self.assertEqual(mail.outbox[0].attachments, [
53
+ ('test.txt', 'A test file content.', 'text/plain')])
54
+
43
55
  def test_send_email_message_to_formats(self):
44
56
  send_email_message(
45
57
  SimpleNamespace(full_email='"Test 1" <test1@example.org>'),