django-pfx 1.7.6.dev43__tar.gz → 1.7.6.dev45__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.
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/PKG-INFO +1 -1
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/PKG-INFO +1 -1
- django_pfx-1.7.6.dev45/django_pfx.egg-info/scm_version.json +8 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/api.views.rst +3 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/model.md +46 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +2 -2
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/pfx_models.py +41 -14
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/locale/fr/LC_MESSAGES/django.po +3 -3
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/migrations/0001_initial.py +9 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/models.py +13 -1
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/basic_api_test.py +28 -0
- django_pfx-1.7.6.dev43/django_pfx.egg-info/scm_version.json +0 -8
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/.gitignore +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/.gitlab-ci.yml +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/.pre-commit-config.yaml +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/LICENSE +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/MANIFEST.in +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/README.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/SOURCES.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/dependency_links.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/requires.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/scm_file_list.json +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/django_pfx.egg-info/top_level.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/Makefile +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/conf.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/index.rst +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/authentication.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/decorator.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/generate_openapi.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/getting_started.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/internationalisation.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/pfx_views.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/profiling.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/settings.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/testing.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/doc/source/user_jobs.md +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/img/pfx.png +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/img/pfx.svg +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/make_messages +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/manage.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/apps.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/email_backend/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/email_backend/memory_email_backend.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/email_backend/q_mailjet_email_backend.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/exceptions.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/locale/fr/LC_MESSAGES/django.mo +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/locale/fr/LC_MESSAGES/django.po +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/mailjet/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/mailjet/mailjet.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/mailjet/message_result.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0002_alter_email_headers.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0003_alter_email_options.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0004_alter_email_mail_from.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0005_lowercase_verbose_names.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0006_alter_email_attachments.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/models/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/models/email.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/providers/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/providers/email_django_q_executor.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/shortcuts.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/tasks.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/templates/emails/base_template.html +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/templates/emails/base_template.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/templates/emails/base_template_subject.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/test.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/views/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/views/email_rest_view.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/apidoc/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/apidoc/parameters.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/apidoc/schema.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/apidoc/tags.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/apps.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/decorator/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/decorator/rest.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/default_settings.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/exceptions.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/decimal_field.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/media_field.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/rich_text_field.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/http/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/http/json_response.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/profile.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/authenticator.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/base.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/email.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/legacy.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/mfa/sms.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/authentication.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/locale.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/profiling.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/request_too_big_middleware.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/middleware/ws_cookie_authentication_middleware.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0005_mfadevice_mfadevice_mfa_device_unique_backend.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0006_alter_pfxuser_managers.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0007_alter_pfxuser_options.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0008_lowercase_verbose_names.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/attachment_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/cache_mixins.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/login_ban.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/mfa_device.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/mfa_user_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/not_null_fields.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/pfx_user.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/serializers/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/serializers/json.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/settings.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/shortcuts.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/sms/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/sms/backends/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/sms/backends/base.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/sms/backends/console.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/sms/backends/memory.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/storage/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/storage/exceptions.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/storage/local_storage.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/storage/s3_storage.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/test.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/version_check.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/authentication_views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/fields.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/filters_views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/locale_views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/mfa_authentication_views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/date_format.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/groups.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/list_count.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/list_items.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/list_order.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/list_search.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/views/rest_views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/xml_test_runner.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/apps.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/locale/fr/LC_MESSAGES/django.mo +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/locale/fr/LC_MESSAGES/django.po +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0003_clean_scheduled_tasks.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0004_userjob_summary_url.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0005_swappable_user_job.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/0006_lowercase_verbose_names.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/models/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/models/user_job.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/models/user_job_attachment.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/providers/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/providers/user_job_django_q_executor.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/providers/user_job_websocket_channel_provider.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/tasks.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/views/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/views/user_job_attachment_view.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/views/user_job_view.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/userjobs/views/user_websocket_consumer.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pyproject.toml +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/requirements.txt +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/serve-doc +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/setup.cfg +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/setup.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/apps.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/channel_group_send_calls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/mfa_urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/ci.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/common.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/settings/dev_default.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/basic_api_errors.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/mfa_test_utils.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/parallel_scenarios.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_api_doc.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_api_doc_search.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_body_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_cache.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_client.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_emails_email_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_emails_email_model.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_emails_q_mailjet_email_backend.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_emails_send_email_message.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_emails_test_tools.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_choices.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_date.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_decimal.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_help_text.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_media_local.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_media_s3.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_minutes_duration.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_one2many.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_rich_text.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_fields_time.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_filters.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_locale_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_mfa_legacy.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_mfa_login_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_mfa_setup_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_perm_tests.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_permissions.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_perms_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_post_migrate_groups_update.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_profiling_middleware.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_settings.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_shortcuts.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_table_file_helpers.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_test_runner.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_timezone_middleware.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_tools.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_user_job_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_user_job_messages.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_user_job_model.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_user_queryset.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_user_websocket.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_verbose_names.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_version_check.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_view_decorators.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_view_fields.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/tests/test_ws_cookie_middleware.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests/views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/ci.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/common.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/settings/dev_default.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/tests/test_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_base_user/views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/models.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/ci.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/common.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/settings/dev_default.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/tests/test_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user/views.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/migrations/0002_lowercase_verbose_names.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/models.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/providers.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/scope.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/ci.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/common.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/settings/dev_default.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/tests/test_user_job.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_custom_user_job/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/migrations/0001_initial.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/migrations/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/models.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/ci.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/common.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/dev.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/dev_custom_example.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/settings/dev_default.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/tests/__init__.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/tests/test_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/tests/test_auth_api.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/tests_user_email_login/urls.py +0 -0
- {django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/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.
|
|
3
|
+
Version: 1.7.6.dev45
|
|
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.
|
|
3
|
+
Version: 1.7.6.dev45
|
|
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
|
|
@@ -102,6 +102,52 @@ Which give the following result on the book service :
|
|
|
102
102
|
}
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
## UniqueConstraint
|
|
106
|
+
|
|
107
|
+
`pfx.pfxcore.models.UniqueConstraint` extends the Django constraint
|
|
108
|
+
to give a better validation error to the [PFX views](./pfx_views.md),
|
|
109
|
+
which return it in their `422` response. It takes two optional
|
|
110
|
+
parameters:
|
|
111
|
+
|
|
112
|
+
* `message`: the error message, formatted with the values of the
|
|
113
|
+
constraint fields. It requires a model inheriting `PFXModelMixin`
|
|
114
|
+
and applies to a constraint on `fields` only.
|
|
115
|
+
* `violation_error_field`: the field to report the error under.
|
|
116
|
+
Without it, Django reports the error globally (`__all__`) as soon as
|
|
117
|
+
the constraint is made of several fields or of expressions.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from django.db import models
|
|
121
|
+
from django.db.models.functions import Lower
|
|
122
|
+
from pfx.pfxcore.models import PFXModelMixin, UniqueConstraint
|
|
123
|
+
|
|
124
|
+
class Book(PFXModelMixin, models.Model):
|
|
125
|
+
name = models.CharField("Name", max_length=100)
|
|
126
|
+
author = models.ForeignKey(
|
|
127
|
+
'tests.Author', on_delete=models.RESTRICT,
|
|
128
|
+
related_name='books', verbose_name="Author")
|
|
129
|
+
|
|
130
|
+
class Meta:
|
|
131
|
+
constraints = [
|
|
132
|
+
UniqueConstraint(
|
|
133
|
+
'author', Lower('name'),
|
|
134
|
+
name='book_unique_author_and_name',
|
|
135
|
+
violation_error_message=(
|
|
136
|
+
"This name is already used for this author."),
|
|
137
|
+
violation_error_field='name')]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
A duplicate name then returns:
|
|
141
|
+
```python
|
|
142
|
+
{
|
|
143
|
+
"name": ["This name is already used for this author."]
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`violation_error_field` changes the validation only: from Django 5.2,
|
|
148
|
+
changing it generates an `AlterConstraint` migration, without any
|
|
149
|
+
change to the database.
|
|
150
|
+
|
|
105
151
|
## Not null char fields
|
|
106
152
|
|
|
107
153
|
To avoid storing a mixture of empty strings and `null` values, while automatically
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po
RENAMED
|
@@ -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-10-
|
|
10
|
+
"POT-Creation-Date: 2026-10-28 14:02+0100\n"
|
|
11
11
|
"PO-Revision-Date: 2021-06-22 23:31+0200\n"
|
|
12
12
|
"Last-Translator: \n"
|
|
13
13
|
"Language-Team: \n"
|
|
@@ -175,7 +175,7 @@ msgstr "MFA forcé"
|
|
|
175
175
|
msgid "sequence"
|
|
176
176
|
msgstr "séquence"
|
|
177
177
|
|
|
178
|
-
#: models/pfx_models.py:
|
|
178
|
+
#: models/pfx_models.py:26
|
|
179
179
|
#, python-format
|
|
180
180
|
msgid "%(model_name)s with this %(field_labels)s already exists."
|
|
181
181
|
msgstr "%(model_name)s avec ce/cette %(field_labels)s existe déjà."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from django.core.exceptions import
|
|
4
|
+
from django.core.exceptions import ValidationError
|
|
5
5
|
from django.db import models
|
|
6
6
|
from django.utils.translation import gettext_lazy as _
|
|
7
7
|
|
|
@@ -9,14 +9,42 @@ logger = logging.getLogger(__name__)
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class UniqueConstraint(models.UniqueConstraint):
|
|
12
|
-
|
|
12
|
+
"""A unique constraint with a richer validation error.
|
|
13
|
+
|
|
14
|
+
:param message: The error message, formatted with the values of the
|
|
15
|
+
constraint fields (``%(name)s already exists``)
|
|
16
|
+
:param violation_error_field: The field to report the error under,
|
|
17
|
+
instead of the global errors (``__all__``)
|
|
18
|
+
"""
|
|
19
|
+
non_db_attrs = (
|
|
20
|
+
*getattr(models.UniqueConstraint, 'non_db_attrs', ()),
|
|
21
|
+
'violation_error_field')
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self, *args, message=None, violation_error_field=None, **kwargs):
|
|
13
25
|
self.message = message or _(
|
|
14
26
|
"%(model_name)s with this %(field_labels)s already exists.")
|
|
27
|
+
self.violation_error_field = violation_error_field
|
|
15
28
|
super().__init__(*args, **kwargs)
|
|
16
29
|
|
|
30
|
+
def validate(self, *args, **kwargs):
|
|
31
|
+
try:
|
|
32
|
+
super().validate(*args, **kwargs)
|
|
33
|
+
except ValidationError as e:
|
|
34
|
+
if not self.violation_error_field:
|
|
35
|
+
raise
|
|
36
|
+
raise ValidationError({self.violation_error_field: e})
|
|
37
|
+
|
|
38
|
+
def __eq__(self, other):
|
|
39
|
+
return super().__eq__(other) and (
|
|
40
|
+
self.violation_error_field ==
|
|
41
|
+
getattr(other, 'violation_error_field', None))
|
|
42
|
+
|
|
17
43
|
def deconstruct(self):
|
|
18
44
|
path, args, kwargs = super().deconstruct()
|
|
19
45
|
kwargs['message'] = self.message
|
|
46
|
+
if self.violation_error_field:
|
|
47
|
+
kwargs['violation_error_field'] = self.violation_error_field
|
|
20
48
|
return path, args, kwargs
|
|
21
49
|
|
|
22
50
|
|
|
@@ -85,8 +113,9 @@ class ErrorMessageMixin():
|
|
|
85
113
|
"""A model mixin to improve mode validation errors."""
|
|
86
114
|
|
|
87
115
|
def validate_constraints(self, exclude=None):
|
|
88
|
-
"""Override
|
|
89
|
-
|
|
116
|
+
"""Override validate_constraints to apply the custom message
|
|
117
|
+
of a :class:`UniqueConstraint`, whatever the field its error is
|
|
118
|
+
reported under.
|
|
90
119
|
"""
|
|
91
120
|
def objgetattr(obj, f):
|
|
92
121
|
v = getattr(obj, f)
|
|
@@ -99,11 +128,11 @@ class ErrorMessageMixin():
|
|
|
99
128
|
try:
|
|
100
129
|
return super().validate_constraints(exclude=exclude)
|
|
101
130
|
except ValidationError as e:
|
|
102
|
-
errors =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
131
|
+
errors = {}
|
|
132
|
+
for key, field_errors in e.update_error_dict({}).items():
|
|
133
|
+
for error in field_errors:
|
|
134
|
+
if (isinstance(error, ValidationError) and
|
|
135
|
+
error.code in ('unique', 'unique_together')):
|
|
107
136
|
model = error.params['model_class']
|
|
108
137
|
unique_check = error.params['unique_check']
|
|
109
138
|
unique = next(filter(
|
|
@@ -114,13 +143,11 @@ class ErrorMessageMixin():
|
|
|
114
143
|
params = dict(error.params)
|
|
115
144
|
params.update({
|
|
116
145
|
f: objgetattr(self, f) for f in unique_check})
|
|
117
|
-
|
|
146
|
+
error = ValidationError(
|
|
118
147
|
message=unique.message,
|
|
119
148
|
code=error.code,
|
|
120
|
-
params=params)
|
|
121
|
-
|
|
122
|
-
non_field_errors.append(error)
|
|
123
|
-
errors[NON_FIELD_ERRORS] = non_field_errors
|
|
149
|
+
params=params)
|
|
150
|
+
errors.setdefault(key, []).append(error)
|
|
124
151
|
raise ValidationError(errors)
|
|
125
152
|
|
|
126
153
|
|
|
@@ -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: 2026-
|
|
11
|
+
"POT-Creation-Date: 2026-10-28 14:02+0100\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:
|
|
21
|
+
#: models.py:58
|
|
22
22
|
msgid "First Name"
|
|
23
23
|
msgstr "Prénom"
|
|
24
24
|
|
|
25
|
-
#: models.py:
|
|
25
|
+
#: models.py:59
|
|
26
26
|
msgid "Last Name"
|
|
27
27
|
msgstr "Nom"
|
|
28
28
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import django.contrib.auth.validators
|
|
5
5
|
import django.db.models.deletion
|
|
6
|
+
import django.db.models.functions.text
|
|
6
7
|
import django.utils.timezone
|
|
7
8
|
from django.db import migrations, models
|
|
8
9
|
|
|
@@ -128,4 +129,12 @@ class Migration(migrations.Migration):
|
|
|
128
129
|
model_name='book',
|
|
129
130
|
constraint=pfx.pfxcore.models.pfx_models.UniqueConstraint(fields=('author', 'name'), message='%(name)s already exists for %(author)s', name='book_unique_author_and_name'),
|
|
130
131
|
),
|
|
132
|
+
migrations.AddConstraint(
|
|
133
|
+
model_name='book',
|
|
134
|
+
constraint=pfx.pfxcore.models.pfx_models.UniqueConstraint(models.F('author'), django.db.models.functions.text.Lower('name'), message='%(model_name)s with this %(field_labels)s already exists.', name='book_unique_author_and_lower_name', violation_error_field='name', violation_error_message='This name is already used for this author.'),
|
|
135
|
+
),
|
|
136
|
+
migrations.AddConstraint(
|
|
137
|
+
model_name='book',
|
|
138
|
+
constraint=pfx.pfxcore.models.pfx_models.UniqueConstraint(fields=('author', 'pages'), message='A book of %(pages)s pages exists for %(author)s', name='book_unique_author_and_pages', violation_error_field='pages'),
|
|
139
|
+
),
|
|
131
140
|
]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.db.models import Q
|
|
3
|
+
from django.db.models.functions import Lower
|
|
3
4
|
from django.utils.functional import cached_property
|
|
4
5
|
from django.utils.translation import gettext_lazy as _
|
|
5
6
|
|
|
@@ -151,7 +152,18 @@ class Book(CacheDependsMixin, PFXModelMixin, models.Model):
|
|
|
151
152
|
UniqueConstraint(
|
|
152
153
|
fields=['author', 'name'],
|
|
153
154
|
name='book_unique_author_and_name',
|
|
154
|
-
message="%(name)s already exists for %(author)s")
|
|
155
|
+
message="%(name)s already exists for %(author)s"),
|
|
156
|
+
UniqueConstraint(
|
|
157
|
+
'author', Lower('name'),
|
|
158
|
+
name='book_unique_author_and_lower_name',
|
|
159
|
+
violation_error_message=(
|
|
160
|
+
"This name is already used for this author."),
|
|
161
|
+
violation_error_field='name'),
|
|
162
|
+
UniqueConstraint(
|
|
163
|
+
fields=['author', 'pages'],
|
|
164
|
+
name='book_unique_author_and_pages',
|
|
165
|
+
message="A book of %(pages)s pages exists for %(author)s",
|
|
166
|
+
violation_error_field='pages')]
|
|
155
167
|
|
|
156
168
|
def __str__(self):
|
|
157
169
|
return f"{self.name}"
|
|
@@ -1055,6 +1055,34 @@ class BasicAPITest(TestAssertMixin, TestCase):
|
|
|
1055
1055
|
response, '__all__.@0',
|
|
1056
1056
|
'The Hobbit already exists for John Ronald Reuel Tolkien')
|
|
1057
1057
|
|
|
1058
|
+
def test_create_unique_error_field(self):
|
|
1059
|
+
"""A constraint on an expression reports its error globally in
|
|
1060
|
+
Django: `violation_error_field` puts it under the field."""
|
|
1061
|
+
response = self.client.post(
|
|
1062
|
+
'/api/books', dict(
|
|
1063
|
+
name="the hobbit",
|
|
1064
|
+
author=self.author1.pk,
|
|
1065
|
+
pub_date="1937-09-21"))
|
|
1066
|
+
self.assertRC(response, 422)
|
|
1067
|
+
self.assertJE(
|
|
1068
|
+
response, 'name.@0', "This name is already used for this author.")
|
|
1069
|
+
self.assertJENotExists(response, '__all__')
|
|
1070
|
+
|
|
1071
|
+
def test_create_unique_custom_message_error_field(self):
|
|
1072
|
+
"""The custom message still applies to an error reported under a
|
|
1073
|
+
field."""
|
|
1074
|
+
response = self.client.post(
|
|
1075
|
+
'/api/books', dict(
|
|
1076
|
+
name="The End of Eternity",
|
|
1077
|
+
author=self.author3.pk,
|
|
1078
|
+
pub_date="1955-01-01",
|
|
1079
|
+
pages=224))
|
|
1080
|
+
self.assertRC(response, 422)
|
|
1081
|
+
self.assertJE(
|
|
1082
|
+
response, 'pages.@0',
|
|
1083
|
+
'A book of 224 pages exists for Isaac Asimov')
|
|
1084
|
+
self.assertJENotExists(response, '__all__')
|
|
1085
|
+
|
|
1058
1086
|
def test_create_invalid_date(self):
|
|
1059
1087
|
response = self.client.post(
|
|
1060
1088
|
'/api/books', dict(
|
|
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
|
|
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
|
|
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
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/email_backend/memory_email_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/locale/fr/LC_MESSAGES/django.mo
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/locale/fr/LC_MESSAGES/django.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0002_alter_email_headers.py
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/migrations/0003_alter_email_options.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/providers/email_django_q_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/templates/emails/base_template.html
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/emails/templates/emails/base_template.txt
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/fields/minutes_duration_field.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo
RENAMED
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/__init__.py
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/makeapidoc.py
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/management/commands/profile.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/operations/__init__.py
RENAMED
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/migrations/operations/permissions.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_pfx-1.7.6.dev43 → django_pfx-1.7.6.dev45}/pfx/pfxcore/models/abstract_pfx_base_user.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|