udata 9.1.2.dev30355__py2.py3-none-any.whl → 9.1.2.dev30454__py2.py3-none-any.whl
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.
Potentially problematic release.
This version of udata might be problematic. Click here for more details.
- tasks/__init__.py +109 -107
- tasks/helpers.py +18 -18
- udata/__init__.py +4 -4
- udata/admin/views.py +5 -5
- udata/api/__init__.py +111 -134
- udata/api/commands.py +45 -37
- udata/api/errors.py +5 -4
- udata/api/fields.py +23 -21
- udata/api/oauth2.py +55 -74
- udata/api/parsers.py +15 -15
- udata/api/signals.py +1 -1
- udata/api_fields.py +137 -89
- udata/app.py +58 -55
- udata/assets.py +5 -5
- udata/auth/__init__.py +37 -26
- udata/auth/forms.py +23 -15
- udata/auth/helpers.py +1 -1
- udata/auth/mails.py +3 -3
- udata/auth/password_validation.py +19 -15
- udata/auth/views.py +94 -68
- udata/commands/__init__.py +71 -69
- udata/commands/cache.py +7 -7
- udata/commands/db.py +201 -140
- udata/commands/dcat.py +36 -30
- udata/commands/fixtures.py +100 -84
- udata/commands/images.py +21 -20
- udata/commands/info.py +17 -20
- udata/commands/init.py +10 -10
- udata/commands/purge.py +12 -13
- udata/commands/serve.py +41 -29
- udata/commands/static.py +16 -18
- udata/commands/test.py +20 -20
- udata/commands/tests/fixtures.py +26 -24
- udata/commands/worker.py +31 -33
- udata/core/__init__.py +12 -12
- udata/core/activity/__init__.py +0 -1
- udata/core/activity/api.py +59 -49
- udata/core/activity/models.py +28 -26
- udata/core/activity/signals.py +1 -1
- udata/core/activity/tasks.py +16 -10
- udata/core/badges/api.py +6 -6
- udata/core/badges/commands.py +14 -13
- udata/core/badges/fields.py +8 -5
- udata/core/badges/forms.py +7 -4
- udata/core/badges/models.py +16 -31
- udata/core/badges/permissions.py +1 -3
- udata/core/badges/signals.py +2 -2
- udata/core/badges/tasks.py +3 -2
- udata/core/badges/tests/test_commands.py +10 -10
- udata/core/badges/tests/test_model.py +24 -31
- udata/core/contact_point/api.py +19 -18
- udata/core/contact_point/api_fields.py +21 -14
- udata/core/contact_point/factories.py +2 -2
- udata/core/contact_point/forms.py +7 -6
- udata/core/contact_point/models.py +3 -5
- udata/core/dataservices/api.py +26 -21
- udata/core/dataservices/factories.py +13 -11
- udata/core/dataservices/models.py +35 -40
- udata/core/dataservices/permissions.py +4 -4
- udata/core/dataservices/rdf.py +40 -17
- udata/core/dataservices/tasks.py +4 -3
- udata/core/dataset/actions.py +10 -10
- udata/core/dataset/activities.py +21 -23
- udata/core/dataset/api.py +321 -298
- udata/core/dataset/api_fields.py +443 -271
- udata/core/dataset/apiv2.py +305 -229
- udata/core/dataset/commands.py +38 -36
- udata/core/dataset/constants.py +61 -54
- udata/core/dataset/csv.py +70 -74
- udata/core/dataset/events.py +39 -32
- udata/core/dataset/exceptions.py +8 -4
- udata/core/dataset/factories.py +57 -65
- udata/core/dataset/forms.py +87 -63
- udata/core/dataset/models.py +336 -280
- udata/core/dataset/permissions.py +9 -6
- udata/core/dataset/preview.py +15 -17
- udata/core/dataset/rdf.py +156 -122
- udata/core/dataset/search.py +92 -77
- udata/core/dataset/signals.py +1 -1
- udata/core/dataset/tasks.py +63 -54
- udata/core/discussions/actions.py +5 -5
- udata/core/discussions/api.py +124 -120
- udata/core/discussions/factories.py +2 -2
- udata/core/discussions/forms.py +9 -7
- udata/core/discussions/metrics.py +1 -3
- udata/core/discussions/models.py +25 -24
- udata/core/discussions/notifications.py +18 -14
- udata/core/discussions/permissions.py +3 -3
- udata/core/discussions/signals.py +4 -4
- udata/core/discussions/tasks.py +24 -28
- udata/core/followers/api.py +32 -33
- udata/core/followers/models.py +9 -9
- udata/core/followers/signals.py +3 -3
- udata/core/jobs/actions.py +7 -7
- udata/core/jobs/api.py +99 -92
- udata/core/jobs/commands.py +48 -49
- udata/core/jobs/forms.py +11 -11
- udata/core/jobs/models.py +6 -6
- udata/core/metrics/__init__.py +2 -2
- udata/core/metrics/commands.py +34 -30
- udata/core/metrics/models.py +2 -4
- udata/core/metrics/signals.py +1 -1
- udata/core/metrics/tasks.py +3 -3
- udata/core/organization/activities.py +12 -15
- udata/core/organization/api.py +167 -174
- udata/core/organization/api_fields.py +183 -124
- udata/core/organization/apiv2.py +32 -32
- udata/core/organization/commands.py +20 -22
- udata/core/organization/constants.py +11 -11
- udata/core/organization/csv.py +17 -15
- udata/core/organization/factories.py +8 -11
- udata/core/organization/forms.py +32 -26
- udata/core/organization/metrics.py +2 -1
- udata/core/organization/models.py +87 -67
- udata/core/organization/notifications.py +18 -14
- udata/core/organization/permissions.py +10 -11
- udata/core/organization/rdf.py +14 -14
- udata/core/organization/search.py +30 -28
- udata/core/organization/signals.py +7 -7
- udata/core/organization/tasks.py +42 -61
- udata/core/owned.py +38 -27
- udata/core/post/api.py +82 -81
- udata/core/post/constants.py +8 -5
- udata/core/post/factories.py +4 -4
- udata/core/post/forms.py +13 -14
- udata/core/post/models.py +20 -22
- udata/core/post/tests/test_api.py +30 -32
- udata/core/reports/api.py +8 -7
- udata/core/reports/constants.py +1 -3
- udata/core/reports/models.py +10 -10
- udata/core/reuse/activities.py +15 -19
- udata/core/reuse/api.py +123 -126
- udata/core/reuse/api_fields.py +120 -85
- udata/core/reuse/apiv2.py +11 -10
- udata/core/reuse/constants.py +23 -23
- udata/core/reuse/csv.py +18 -18
- udata/core/reuse/factories.py +5 -9
- udata/core/reuse/forms.py +24 -21
- udata/core/reuse/models.py +55 -51
- udata/core/reuse/permissions.py +2 -2
- udata/core/reuse/search.py +49 -46
- udata/core/reuse/signals.py +1 -1
- udata/core/reuse/tasks.py +4 -5
- udata/core/site/api.py +47 -50
- udata/core/site/factories.py +2 -2
- udata/core/site/forms.py +4 -5
- udata/core/site/models.py +94 -63
- udata/core/site/rdf.py +14 -14
- udata/core/spam/api.py +16 -9
- udata/core/spam/constants.py +4 -4
- udata/core/spam/fields.py +13 -7
- udata/core/spam/models.py +27 -20
- udata/core/spam/signals.py +1 -1
- udata/core/spam/tests/test_spam.py +6 -5
- udata/core/spatial/api.py +72 -80
- udata/core/spatial/api_fields.py +73 -58
- udata/core/spatial/commands.py +67 -64
- udata/core/spatial/constants.py +3 -3
- udata/core/spatial/factories.py +37 -54
- udata/core/spatial/forms.py +27 -26
- udata/core/spatial/geoids.py +17 -17
- udata/core/spatial/models.py +43 -47
- udata/core/spatial/tasks.py +2 -1
- udata/core/spatial/tests/test_api.py +115 -130
- udata/core/spatial/tests/test_fields.py +74 -77
- udata/core/spatial/tests/test_geoid.py +22 -22
- udata/core/spatial/tests/test_models.py +5 -7
- udata/core/spatial/translations.py +16 -16
- udata/core/storages/__init__.py +16 -18
- udata/core/storages/api.py +66 -64
- udata/core/storages/tasks.py +7 -7
- udata/core/storages/utils.py +15 -15
- udata/core/storages/views.py +5 -6
- udata/core/tags/api.py +17 -14
- udata/core/tags/csv.py +4 -4
- udata/core/tags/models.py +8 -5
- udata/core/tags/tasks.py +11 -13
- udata/core/tags/views.py +4 -4
- udata/core/topic/api.py +84 -73
- udata/core/topic/apiv2.py +157 -127
- udata/core/topic/factories.py +3 -4
- udata/core/topic/forms.py +12 -14
- udata/core/topic/models.py +14 -19
- udata/core/topic/parsers.py +26 -26
- udata/core/user/activities.py +30 -29
- udata/core/user/api.py +151 -152
- udata/core/user/api_fields.py +132 -100
- udata/core/user/apiv2.py +7 -7
- udata/core/user/commands.py +38 -38
- udata/core/user/factories.py +8 -9
- udata/core/user/forms.py +14 -11
- udata/core/user/metrics.py +2 -2
- udata/core/user/models.py +68 -69
- udata/core/user/permissions.py +4 -5
- udata/core/user/rdf.py +7 -8
- udata/core/user/tasks.py +2 -2
- udata/core/user/tests/test_user_model.py +24 -16
- udata/cors.py +99 -0
- udata/db/tasks.py +2 -1
- udata/entrypoints.py +35 -31
- udata/errors.py +2 -1
- udata/event/values.py +6 -6
- udata/factories.py +2 -2
- udata/features/identicon/api.py +5 -6
- udata/features/identicon/backends.py +48 -55
- udata/features/identicon/tests/test_backends.py +4 -5
- udata/features/notifications/__init__.py +0 -1
- udata/features/notifications/actions.py +9 -9
- udata/features/notifications/api.py +17 -13
- udata/features/territories/__init__.py +12 -10
- udata/features/territories/api.py +14 -15
- udata/features/territories/models.py +23 -28
- udata/features/transfer/actions.py +8 -11
- udata/features/transfer/api.py +84 -77
- udata/features/transfer/factories.py +2 -1
- udata/features/transfer/models.py +11 -12
- udata/features/transfer/notifications.py +19 -15
- udata/features/transfer/permissions.py +5 -5
- udata/forms/__init__.py +5 -2
- udata/forms/fields.py +164 -172
- udata/forms/validators.py +19 -22
- udata/forms/widgets.py +9 -13
- udata/frontend/__init__.py +31 -26
- udata/frontend/csv.py +68 -58
- udata/frontend/markdown.py +40 -44
- udata/harvest/actions.py +89 -77
- udata/harvest/api.py +294 -238
- udata/harvest/backends/__init__.py +4 -4
- udata/harvest/backends/base.py +128 -111
- udata/harvest/backends/dcat.py +80 -66
- udata/harvest/commands.py +56 -60
- udata/harvest/csv.py +8 -8
- udata/harvest/exceptions.py +6 -3
- udata/harvest/filters.py +24 -23
- udata/harvest/forms.py +27 -28
- udata/harvest/models.py +88 -80
- udata/harvest/notifications.py +15 -10
- udata/harvest/signals.py +13 -13
- udata/harvest/tasks.py +11 -10
- udata/harvest/tests/factories.py +23 -24
- udata/harvest/tests/test_actions.py +136 -166
- udata/harvest/tests/test_api.py +220 -214
- udata/harvest/tests/test_base_backend.py +117 -112
- udata/harvest/tests/test_dcat_backend.py +380 -308
- udata/harvest/tests/test_filters.py +33 -22
- udata/harvest/tests/test_models.py +11 -14
- udata/harvest/tests/test_notifications.py +6 -7
- udata/harvest/tests/test_tasks.py +7 -6
- udata/i18n.py +237 -78
- udata/linkchecker/backends.py +5 -11
- udata/linkchecker/checker.py +23 -22
- udata/linkchecker/commands.py +4 -6
- udata/linkchecker/models.py +6 -6
- udata/linkchecker/tasks.py +18 -20
- udata/mail.py +21 -21
- udata/migrations/2020-07-24-remove-s-from-scope-oauth.py +9 -8
- udata/migrations/2020-08-24-add-fs-filename.py +9 -8
- udata/migrations/2020-09-28-update-reuses-datasets-metrics.py +5 -4
- udata/migrations/2020-10-16-migrate-ods-resources.py +9 -10
- udata/migrations/2021-04-08-update-schema-with-new-structure.py +8 -7
- udata/migrations/2021-05-27-fix-default-schema-name.py +7 -6
- udata/migrations/2021-07-05-remove-unused-badges.py +17 -15
- udata/migrations/2021-07-07-update-schema-for-community-resources.py +7 -6
- udata/migrations/2021-08-17-follow-integrity.py +5 -4
- udata/migrations/2021-08-17-harvest-integrity.py +13 -12
- udata/migrations/2021-08-17-oauth2client-integrity.py +5 -4
- udata/migrations/2021-08-17-transfer-integrity.py +5 -4
- udata/migrations/2021-08-17-users-integrity.py +9 -8
- udata/migrations/2021-12-14-reuse-topics.py +7 -6
- udata/migrations/2022-04-21-improve-extension-detection.py +8 -7
- udata/migrations/2022-09-22-clean-inactive-harvest-datasets.py +16 -14
- udata/migrations/2022-10-10-add-fs_uniquifier-to-user-model.py +6 -6
- udata/migrations/2022-10-10-migrate-harvest-extras.py +36 -26
- udata/migrations/2023-02-08-rename-internal-dates.py +46 -28
- udata/migrations/2024-01-29-fix-reuse-and-dataset-with-private-None.py +10 -8
- udata/migrations/2024-03-22-migrate-activity-kwargs-to-extras.py +6 -4
- udata/migrations/2024-06-11-fix-reuse-datasets-references.py +7 -6
- udata/migrations/__init__.py +123 -105
- udata/models/__init__.py +4 -4
- udata/mongo/__init__.py +13 -11
- udata/mongo/badges_field.py +3 -2
- udata/mongo/datetime_fields.py +13 -12
- udata/mongo/document.py +17 -16
- udata/mongo/engine.py +15 -16
- udata/mongo/errors.py +2 -1
- udata/mongo/extras_fields.py +30 -20
- udata/mongo/queryset.py +12 -12
- udata/mongo/slug_fields.py +38 -28
- udata/mongo/taglist_field.py +1 -2
- udata/mongo/url_field.py +5 -5
- udata/mongo/uuid_fields.py +4 -3
- udata/notifications/__init__.py +1 -1
- udata/notifications/mattermost.py +10 -9
- udata/rdf.py +167 -188
- udata/routing.py +40 -45
- udata/search/__init__.py +18 -19
- udata/search/adapter.py +17 -16
- udata/search/commands.py +44 -51
- udata/search/fields.py +13 -20
- udata/search/query.py +23 -18
- udata/search/result.py +9 -10
- udata/sentry.py +21 -19
- udata/settings.py +262 -198
- udata/sitemap.py +8 -6
- udata/storage/s3.py +20 -13
- udata/tags.py +4 -5
- udata/tasks.py +43 -42
- udata/tests/__init__.py +9 -6
- udata/tests/api/__init__.py +8 -6
- udata/tests/api/test_auth_api.py +395 -321
- udata/tests/api/test_base_api.py +33 -35
- udata/tests/api/test_contact_points.py +7 -9
- udata/tests/api/test_dataservices_api.py +211 -158
- udata/tests/api/test_datasets_api.py +823 -812
- udata/tests/api/test_follow_api.py +13 -15
- udata/tests/api/test_me_api.py +95 -112
- udata/tests/api/test_organizations_api.py +301 -339
- udata/tests/api/test_reports_api.py +35 -25
- udata/tests/api/test_reuses_api.py +134 -139
- udata/tests/api/test_swagger.py +5 -5
- udata/tests/api/test_tags_api.py +18 -25
- udata/tests/api/test_topics_api.py +94 -94
- udata/tests/api/test_transfer_api.py +53 -48
- udata/tests/api/test_user_api.py +128 -141
- udata/tests/apiv2/test_datasets.py +290 -198
- udata/tests/apiv2/test_me_api.py +10 -11
- udata/tests/apiv2/test_organizations.py +56 -74
- udata/tests/apiv2/test_swagger.py +5 -5
- udata/tests/apiv2/test_topics.py +69 -87
- udata/tests/cli/test_cli_base.py +8 -8
- udata/tests/cli/test_db_cli.py +21 -19
- udata/tests/dataservice/test_dataservice_tasks.py +8 -12
- udata/tests/dataset/test_csv_adapter.py +44 -35
- udata/tests/dataset/test_dataset_actions.py +2 -3
- udata/tests/dataset/test_dataset_commands.py +7 -8
- udata/tests/dataset/test_dataset_events.py +36 -29
- udata/tests/dataset/test_dataset_model.py +224 -217
- udata/tests/dataset/test_dataset_rdf.py +142 -131
- udata/tests/dataset/test_dataset_tasks.py +15 -15
- udata/tests/dataset/test_resource_preview.py +10 -13
- udata/tests/features/territories/__init__.py +9 -13
- udata/tests/features/territories/test_territories_api.py +71 -91
- udata/tests/forms/test_basic_fields.py +7 -7
- udata/tests/forms/test_current_user_field.py +39 -66
- udata/tests/forms/test_daterange_field.py +31 -39
- udata/tests/forms/test_dict_field.py +28 -26
- udata/tests/forms/test_extras_fields.py +102 -76
- udata/tests/forms/test_form_field.py +8 -8
- udata/tests/forms/test_image_field.py +33 -26
- udata/tests/forms/test_model_field.py +134 -123
- udata/tests/forms/test_model_list_field.py +7 -7
- udata/tests/forms/test_nested_model_list_field.py +117 -79
- udata/tests/forms/test_publish_as_field.py +36 -65
- udata/tests/forms/test_reference_field.py +34 -53
- udata/tests/forms/test_user_forms.py +23 -21
- udata/tests/forms/test_uuid_field.py +6 -10
- udata/tests/frontend/__init__.py +9 -6
- udata/tests/frontend/test_auth.py +7 -6
- udata/tests/frontend/test_csv.py +81 -96
- udata/tests/frontend/test_hooks.py +43 -43
- udata/tests/frontend/test_markdown.py +211 -191
- udata/tests/helpers.py +32 -37
- udata/tests/models.py +2 -2
- udata/tests/organization/test_csv_adapter.py +21 -16
- udata/tests/organization/test_notifications.py +11 -18
- udata/tests/organization/test_organization_model.py +13 -13
- udata/tests/organization/test_organization_rdf.py +29 -22
- udata/tests/organization/test_organization_tasks.py +16 -17
- udata/tests/plugin.py +79 -73
- udata/tests/reuse/test_reuse_model.py +21 -21
- udata/tests/reuse/test_reuse_task.py +11 -13
- udata/tests/search/__init__.py +11 -12
- udata/tests/search/test_adapter.py +60 -70
- udata/tests/search/test_query.py +16 -16
- udata/tests/search/test_results.py +10 -7
- udata/tests/site/test_site_api.py +11 -16
- udata/tests/site/test_site_metrics.py +20 -30
- udata/tests/site/test_site_model.py +4 -5
- udata/tests/site/test_site_rdf.py +94 -78
- udata/tests/test_activity.py +17 -17
- udata/tests/test_cors.py +62 -0
- udata/tests/test_discussions.py +292 -299
- udata/tests/test_i18n.py +37 -40
- udata/tests/test_linkchecker.py +91 -85
- udata/tests/test_mail.py +13 -17
- udata/tests/test_migrations.py +219 -180
- udata/tests/test_model.py +164 -157
- udata/tests/test_notifications.py +17 -17
- udata/tests/test_owned.py +14 -14
- udata/tests/test_rdf.py +25 -23
- udata/tests/test_routing.py +89 -93
- udata/tests/test_storages.py +137 -128
- udata/tests/test_tags.py +44 -46
- udata/tests/test_topics.py +7 -7
- udata/tests/test_transfer.py +42 -49
- udata/tests/test_uris.py +160 -161
- udata/tests/test_utils.py +79 -71
- udata/tests/user/test_user_rdf.py +5 -9
- udata/tests/workers/test_jobs_commands.py +57 -58
- udata/tests/workers/test_tasks_routing.py +23 -29
- udata/tests/workers/test_workers_api.py +125 -131
- udata/tests/workers/test_workers_helpers.py +6 -6
- udata/tracking.py +4 -6
- udata/uris.py +45 -46
- udata/utils.py +68 -66
- udata/wsgi.py +1 -1
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/METADATA +7 -3
- udata-9.1.2.dev30454.dist-info/RECORD +706 -0
- udata-9.1.2.dev30355.dist-info/RECORD +0 -704
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/LICENSE +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/WHEEL +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/entry_points.txt +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/top_level.txt +0 -0
udata/core/organization/forms.py
CHANGED
|
@@ -4,27 +4,27 @@ from udata.auth import current_user
|
|
|
4
4
|
from udata.forms import Form, ModelForm, fields, validators
|
|
5
5
|
from udata.i18n import lazy_gettext as _
|
|
6
6
|
|
|
7
|
-
from .models import Organization, MembershipRequest, Member
|
|
8
7
|
from .constants import DESCRIPTION_SIZE_LIMIT, LOGO_SIZES, ORG_ROLES, TITLE_SIZE_LIMIT
|
|
8
|
+
from .models import Member, MembershipRequest, Organization
|
|
9
9
|
|
|
10
10
|
__all__ = (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
"OrganizationForm",
|
|
12
|
+
"MemberForm",
|
|
13
|
+
"MembershipRequestForm",
|
|
14
|
+
"MembershipRefuseForm",
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def org_bid_check(form, field):
|
|
19
19
|
if field.data:
|
|
20
20
|
# EID checks are country dependant. Following one is suitable for France.
|
|
21
|
-
if current_app.config.get(
|
|
21
|
+
if current_app.config.get("ORG_BID_FORMAT") == "siret":
|
|
22
22
|
siret_number = str(field.data)
|
|
23
23
|
# Length control done here instead of using WTForm validator because field must remain optional.
|
|
24
24
|
if len(siret_number) != 14:
|
|
25
|
-
raise validators.ValidationError(_(
|
|
25
|
+
raise validators.ValidationError(_("A siret number is made of 14 digits"))
|
|
26
26
|
# Siret exception for the french postal service which business number id does not match the algorithm.
|
|
27
|
-
if siret_number ==
|
|
27
|
+
if siret_number == "35600000000048":
|
|
28
28
|
return
|
|
29
29
|
# Checksum verification on only the SIREN part, the 9 first digits.
|
|
30
30
|
try:
|
|
@@ -33,37 +33,40 @@ def org_bid_check(form, field):
|
|
|
33
33
|
chiffres = [chiffre - 9 if chiffre > 9 else chiffre for chiffre in chiffres]
|
|
34
34
|
total = sum(chiffres)
|
|
35
35
|
except ValueError:
|
|
36
|
-
raise validators.ValidationError(_(
|
|
36
|
+
raise validators.ValidationError(_("A siret number is only made of digits"))
|
|
37
37
|
|
|
38
38
|
if not total % 10 == 0:
|
|
39
|
-
raise validators.ValidationError(_(
|
|
39
|
+
raise validators.ValidationError(_("Invalid Siret number"))
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class OrganizationForm(ModelForm):
|
|
43
43
|
model_class = Organization
|
|
44
44
|
|
|
45
|
-
name = fields.StringField(
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
name = fields.StringField(
|
|
46
|
+
_("Name"), [validators.DataRequired(), validators.Length(max=TITLE_SIZE_LIMIT)]
|
|
47
|
+
)
|
|
48
|
+
acronym = fields.StringField(_("Acronym"), description=_("Shorter organization name"))
|
|
48
49
|
description = fields.MarkdownField(
|
|
49
|
-
_(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
_("Description"),
|
|
51
|
+
[validators.DataRequired(), validators.Length(max=DESCRIPTION_SIZE_LIMIT)],
|
|
52
|
+
description=_("The details about your organization"),
|
|
53
|
+
)
|
|
54
|
+
url = fields.URLField(_("Website"), description=_("The organization website URL"))
|
|
55
|
+
logo = fields.ImageField(_("Logo"), sizes=LOGO_SIZES)
|
|
56
|
+
business_number_id = fields.StringField(
|
|
57
|
+
_("Business id"), [org_bid_check], description=_("Business identification number")
|
|
58
|
+
)
|
|
56
59
|
|
|
57
60
|
deleted = fields.DateTimeField()
|
|
58
61
|
extras = fields.ExtrasField()
|
|
59
62
|
|
|
60
63
|
def save(self, commit=True, **kwargs):
|
|
61
|
-
|
|
64
|
+
"""Register the current user as admin on creation"""
|
|
62
65
|
org = super(OrganizationForm, self).save(commit=False, **kwargs)
|
|
63
66
|
|
|
64
67
|
if not org.id:
|
|
65
68
|
user = current_user._get_current_object()
|
|
66
|
-
member = Member(user=user, role=
|
|
69
|
+
member = Member(user=user, role="admin")
|
|
67
70
|
org.members.append(member)
|
|
68
71
|
org.count_members()
|
|
69
72
|
|
|
@@ -77,16 +80,19 @@ class MembershipRequestForm(ModelForm):
|
|
|
77
80
|
model_class = MembershipRequest
|
|
78
81
|
|
|
79
82
|
user = fields.CurrentUserField()
|
|
80
|
-
comment = fields.StringField(_(
|
|
83
|
+
comment = fields.StringField(_("Comment"), [validators.DataRequired()])
|
|
81
84
|
|
|
82
85
|
|
|
83
86
|
class MembershipRefuseForm(Form):
|
|
84
|
-
comment = fields.StringField(_(
|
|
87
|
+
comment = fields.StringField(_("Comment"), [validators.DataRequired()])
|
|
85
88
|
|
|
86
89
|
|
|
87
90
|
class MemberForm(ModelForm):
|
|
88
91
|
model_class = Member
|
|
89
92
|
|
|
90
93
|
role = fields.SelectField(
|
|
91
|
-
_(
|
|
92
|
-
|
|
94
|
+
_("Role"),
|
|
95
|
+
default="editor",
|
|
96
|
+
choices=list(ORG_ROLES.items()),
|
|
97
|
+
validators=[validators.DataRequired()],
|
|
98
|
+
)
|
|
@@ -2,33 +2,46 @@ from datetime import datetime
|
|
|
2
2
|
from itertools import chain
|
|
3
3
|
|
|
4
4
|
from blinker import Signal
|
|
5
|
-
from mongoengine.signals import
|
|
5
|
+
from mongoengine.signals import post_save, pre_save
|
|
6
6
|
from werkzeug.utils import cached_property
|
|
7
7
|
|
|
8
8
|
from udata.core.badges.models import BadgeMixin
|
|
9
9
|
from udata.core.metrics.models import WithMetrics
|
|
10
10
|
from udata.core.storages import avatars, default_image_basename
|
|
11
11
|
from udata.frontend.markdown import mdstrip
|
|
12
|
-
from udata.mongo import db
|
|
13
12
|
from udata.i18n import lazy_gettext as _
|
|
13
|
+
from udata.mongo import db
|
|
14
14
|
from udata.uris import endpoint_for
|
|
15
|
-
from .constants import ASSOCIATION, CERTIFIED, COMPANY, LOCAL_AUTHORITY, LOGO_SIZES, ORG_BID_SIZE_LIMIT, ORG_ROLES, DEFAULT_ROLE, MEMBERSHIP_STATUS, LOGO_MAX_SIZE, PUBLIC_SERVICE
|
|
16
15
|
|
|
16
|
+
from .constants import (
|
|
17
|
+
ASSOCIATION,
|
|
18
|
+
CERTIFIED,
|
|
19
|
+
COMPANY,
|
|
20
|
+
DEFAULT_ROLE,
|
|
21
|
+
LOCAL_AUTHORITY,
|
|
22
|
+
LOGO_MAX_SIZE,
|
|
23
|
+
LOGO_SIZES,
|
|
24
|
+
MEMBERSHIP_STATUS,
|
|
25
|
+
ORG_BID_SIZE_LIMIT,
|
|
26
|
+
ORG_ROLES,
|
|
27
|
+
PUBLIC_SERVICE,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
__all__ = ("Organization", "Team", "Member", "MembershipRequest")
|
|
17
31
|
|
|
18
|
-
__all__ = ('Organization', 'Team', 'Member', 'MembershipRequest')
|
|
19
32
|
|
|
20
33
|
class Team(db.EmbeddedDocument):
|
|
21
34
|
name = db.StringField(required=True)
|
|
22
35
|
slug = db.SlugField(
|
|
23
|
-
max_length=255, required=True, populate_from=
|
|
24
|
-
|
|
36
|
+
max_length=255, required=True, populate_from="name", update=True, unique=False
|
|
37
|
+
)
|
|
25
38
|
description = db.StringField()
|
|
26
39
|
|
|
27
|
-
members = db.ListField(db.ReferenceField(
|
|
40
|
+
members = db.ListField(db.ReferenceField("User"))
|
|
28
41
|
|
|
29
42
|
|
|
30
43
|
class Member(db.EmbeddedDocument):
|
|
31
|
-
user = db.ReferenceField(
|
|
44
|
+
user = db.ReferenceField("User")
|
|
32
45
|
role = db.StringField(choices=list(ORG_ROLES), default=DEFAULT_ROLE)
|
|
33
46
|
since = db.DateTimeField(default=datetime.utcnow, required=True)
|
|
34
47
|
|
|
@@ -38,18 +51,18 @@ class Member(db.EmbeddedDocument):
|
|
|
38
51
|
|
|
39
52
|
|
|
40
53
|
class MembershipRequest(db.EmbeddedDocument):
|
|
41
|
-
|
|
54
|
+
"""
|
|
42
55
|
Pending organization membership requests
|
|
43
|
-
|
|
56
|
+
"""
|
|
57
|
+
|
|
44
58
|
id = db.AutoUUIDField()
|
|
45
|
-
user = db.ReferenceField(
|
|
46
|
-
status = db.StringField(
|
|
47
|
-
choices=list(MEMBERSHIP_STATUS), default='pending')
|
|
59
|
+
user = db.ReferenceField("User")
|
|
60
|
+
status = db.StringField(choices=list(MEMBERSHIP_STATUS), default="pending")
|
|
48
61
|
|
|
49
62
|
created = db.DateTimeField(default=datetime.utcnow, required=True)
|
|
50
63
|
|
|
51
64
|
handled_on = db.DateTimeField()
|
|
52
|
-
handled_by = db.ReferenceField(
|
|
65
|
+
handled_by = db.ReferenceField("User")
|
|
53
66
|
|
|
54
67
|
comment = db.StringField()
|
|
55
68
|
refusal_comment = db.StringField()
|
|
@@ -73,13 +86,15 @@ class OrganizationQuerySet(db.BaseQuerySet):
|
|
|
73
86
|
class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
74
87
|
name = db.StringField(required=True)
|
|
75
88
|
acronym = db.StringField(max_length=128)
|
|
76
|
-
slug = db.SlugField(
|
|
77
|
-
|
|
89
|
+
slug = db.SlugField(
|
|
90
|
+
max_length=255, required=True, populate_from="name", update=True, follow=True
|
|
91
|
+
)
|
|
78
92
|
description = db.StringField(required=True)
|
|
79
93
|
url = db.StringField()
|
|
80
94
|
image_url = db.StringField()
|
|
81
|
-
logo = db.ImageField(
|
|
82
|
-
|
|
95
|
+
logo = db.ImageField(
|
|
96
|
+
fs=avatars, basename=default_image_basename, max_size=LOGO_MAX_SIZE, thumbnails=LOGO_SIZES
|
|
97
|
+
)
|
|
83
98
|
business_number_id = db.StringField(max_length=ORG_BID_SIZE_LIMIT)
|
|
84
99
|
|
|
85
100
|
members = db.ListField(db.EmbeddedDocumentField(Member))
|
|
@@ -93,38 +108,38 @@ class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
|
93
108
|
deleted = db.DateTimeField()
|
|
94
109
|
|
|
95
110
|
meta = {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
"indexes": [
|
|
112
|
+
"$name",
|
|
113
|
+
"created_at",
|
|
114
|
+
"slug",
|
|
115
|
+
"metrics.reuses",
|
|
116
|
+
"metrics.datasets",
|
|
117
|
+
"metrics.followers",
|
|
118
|
+
"metrics.views",
|
|
119
|
+
"last_modified",
|
|
105
120
|
],
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
121
|
+
"ordering": ["-created_at"],
|
|
122
|
+
"queryset_class": OrganizationQuerySet,
|
|
123
|
+
"auto_create_index_on_save": True,
|
|
109
124
|
}
|
|
110
125
|
|
|
111
126
|
def __str__(self):
|
|
112
|
-
return self.name or
|
|
127
|
+
return self.name or ""
|
|
113
128
|
|
|
114
129
|
__badges__ = {
|
|
115
|
-
PUBLIC_SERVICE: _(
|
|
116
|
-
CERTIFIED: _(
|
|
117
|
-
ASSOCIATION: _(
|
|
118
|
-
COMPANY: _(
|
|
119
|
-
LOCAL_AUTHORITY: _(
|
|
130
|
+
PUBLIC_SERVICE: _("Public Service"),
|
|
131
|
+
CERTIFIED: _("Certified"),
|
|
132
|
+
ASSOCIATION: _("Association"),
|
|
133
|
+
COMPANY: _("Company"),
|
|
134
|
+
LOCAL_AUTHORITY: _("Local authority"),
|
|
120
135
|
}
|
|
121
136
|
|
|
122
137
|
__metrics_keys__ = [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
"datasets",
|
|
139
|
+
"members",
|
|
140
|
+
"reuses",
|
|
141
|
+
"followers",
|
|
142
|
+
"views",
|
|
128
143
|
]
|
|
129
144
|
|
|
130
145
|
before_save = Signal()
|
|
@@ -141,13 +156,13 @@ class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
|
141
156
|
@classmethod
|
|
142
157
|
def post_save(cls, sender, document, **kwargs):
|
|
143
158
|
cls.after_save.send(document)
|
|
144
|
-
if kwargs.get(
|
|
159
|
+
if kwargs.get("created"):
|
|
145
160
|
cls.on_create.send(document)
|
|
146
161
|
else:
|
|
147
162
|
cls.on_update.send(document)
|
|
148
163
|
|
|
149
164
|
def url_for(self, *args, **kwargs):
|
|
150
|
-
return endpoint_for(
|
|
165
|
+
return endpoint_for("organizations.show", "api.organization", org=self, *args, **kwargs)
|
|
151
166
|
|
|
152
167
|
display_url = property(url_for)
|
|
153
168
|
|
|
@@ -157,15 +172,15 @@ class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
|
157
172
|
|
|
158
173
|
@property
|
|
159
174
|
def pending_requests(self):
|
|
160
|
-
return [r for r in self.requests if r.status ==
|
|
175
|
+
return [r for r in self.requests if r.status == "pending"]
|
|
161
176
|
|
|
162
177
|
@property
|
|
163
178
|
def refused_requests(self):
|
|
164
|
-
return [r for r in self.requests if r.status ==
|
|
179
|
+
return [r for r in self.requests if r.status == "refused"]
|
|
165
180
|
|
|
166
181
|
@property
|
|
167
182
|
def accepted_requests(self):
|
|
168
|
-
return [r for r in self.requests if r.status ==
|
|
183
|
+
return [r for r in self.requests if r.status == "accepted"]
|
|
169
184
|
|
|
170
185
|
@property
|
|
171
186
|
def certified(self):
|
|
@@ -199,11 +214,11 @@ class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
|
199
214
|
|
|
200
215
|
def is_admin(self, user):
|
|
201
216
|
member = self.member(user)
|
|
202
|
-
return member is not None and member.role ==
|
|
217
|
+
return member is not None and member.role == "admin"
|
|
203
218
|
|
|
204
219
|
def pending_request(self, user):
|
|
205
220
|
for request in self.requests:
|
|
206
|
-
if request.user == user and request.status ==
|
|
221
|
+
if request.user == user and request.status == "pending":
|
|
207
222
|
return request
|
|
208
223
|
return None
|
|
209
224
|
|
|
@@ -217,58 +232,63 @@ class Organization(WithMetrics, BadgeMixin, db.Datetimed, db.Document):
|
|
|
217
232
|
|
|
218
233
|
def check_availability(self):
|
|
219
234
|
from udata.models import Dataset # Circular imports.
|
|
235
|
+
|
|
220
236
|
# Performances: only check the first 20 datasets for now.
|
|
221
237
|
return chain(
|
|
222
|
-
*[
|
|
223
|
-
|
|
238
|
+
*[
|
|
239
|
+
dataset.check_availability()
|
|
240
|
+
for dataset in Dataset.objects(organization=self).visible()[:20]
|
|
241
|
+
]
|
|
224
242
|
)
|
|
225
243
|
|
|
226
244
|
@cached_property
|
|
227
245
|
def json_ld(self):
|
|
228
|
-
type_ =
|
|
229
|
-
else 'Organization'
|
|
246
|
+
type_ = "GovernmentOrganization" if self.public_service else "Organization"
|
|
230
247
|
|
|
231
248
|
result = {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
249
|
+
"@context": "http://schema.org",
|
|
250
|
+
"@type": type_,
|
|
251
|
+
"@id": str(self.id),
|
|
252
|
+
"alternateName": self.slug,
|
|
253
|
+
"url": endpoint_for("organizations.show", "api.organization", org=self, _external=True),
|
|
254
|
+
"name": self.name,
|
|
255
|
+
"dateCreated": self.created_at.isoformat(),
|
|
256
|
+
"dateModified": self.last_modified.isoformat(),
|
|
240
257
|
}
|
|
241
258
|
|
|
242
259
|
if self.description:
|
|
243
|
-
result[
|
|
260
|
+
result["description"] = mdstrip(self.description)
|
|
244
261
|
|
|
245
262
|
logo = self.logo(external=True)
|
|
246
263
|
if logo:
|
|
247
|
-
result[
|
|
264
|
+
result["logo"] = logo
|
|
248
265
|
|
|
249
266
|
return result
|
|
250
267
|
|
|
251
268
|
@property
|
|
252
269
|
def views_count(self):
|
|
253
|
-
return self.metrics.get(
|
|
270
|
+
return self.metrics.get("views", 0)
|
|
254
271
|
|
|
255
272
|
def count_members(self):
|
|
256
|
-
self.metrics[
|
|
273
|
+
self.metrics["members"] = len(self.members)
|
|
257
274
|
self.save()
|
|
258
275
|
|
|
259
276
|
def count_datasets(self):
|
|
260
277
|
from udata.models import Dataset
|
|
261
|
-
|
|
278
|
+
|
|
279
|
+
self.metrics["datasets"] = Dataset.objects(organization=self).visible().count()
|
|
262
280
|
self.save()
|
|
263
281
|
|
|
264
282
|
def count_reuses(self):
|
|
265
283
|
from udata.models import Reuse
|
|
266
|
-
|
|
284
|
+
|
|
285
|
+
self.metrics["reuses"] = Reuse.objects(organization=self).visible().count()
|
|
267
286
|
self.save()
|
|
268
287
|
|
|
269
288
|
def count_followers(self):
|
|
270
289
|
from udata.models import Follow
|
|
271
|
-
|
|
290
|
+
|
|
291
|
+
self.metrics["followers"] = Follow.objects(until=None).followers(self).count()
|
|
272
292
|
self.save()
|
|
273
293
|
|
|
274
294
|
|
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
from udata.features.notifications.actions import notifier
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
import logging
|
|
5
2
|
|
|
3
|
+
from udata.features.notifications.actions import notifier
|
|
4
|
+
|
|
6
5
|
log = logging.getLogger(__name__)
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
@notifier(
|
|
8
|
+
@notifier("membership_request")
|
|
10
9
|
def membership_request_notifications(user):
|
|
11
|
-
|
|
10
|
+
"""Notify user about pending membership requests"""
|
|
12
11
|
orgs = [o for o in user.organizations if o.is_admin(user)]
|
|
13
12
|
notifications = []
|
|
14
13
|
|
|
15
14
|
for org in orgs:
|
|
16
15
|
for request in org.pending_requests:
|
|
17
|
-
notifications.append(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
notifications.append(
|
|
17
|
+
(
|
|
18
|
+
request.created,
|
|
19
|
+
{
|
|
20
|
+
"id": request.id,
|
|
21
|
+
"organization": org.id,
|
|
22
|
+
"user": {
|
|
23
|
+
"id": request.user.id,
|
|
24
|
+
"fullname": request.user.fullname,
|
|
25
|
+
"avatar": str(request.user.avatar),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
)
|
|
26
30
|
|
|
27
31
|
return notifications
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
from collections import namedtuple
|
|
2
2
|
from functools import partial
|
|
3
3
|
|
|
4
|
-
from udata.auth import current_user, identity_loaded
|
|
4
|
+
from udata.auth import Permission, current_user, identity_loaded
|
|
5
5
|
from udata.models import Organization
|
|
6
6
|
from udata.utils import get_by
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
OrganizationEditorNeed = partial(OrganizationNeed, 'editor')
|
|
8
|
+
OrganizationNeed = namedtuple("organization", ("role", "value"))
|
|
9
|
+
OrganizationAdminNeed = partial(OrganizationNeed, "admin")
|
|
10
|
+
OrganizationEditorNeed = partial(OrganizationNeed, "editor")
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class EditOrganizationPermission(Permission):
|
|
15
|
-
|
|
14
|
+
"""Permissions to edit organization assets"""
|
|
15
|
+
|
|
16
16
|
def __init__(self, org):
|
|
17
17
|
need = OrganizationAdminNeed(org.id)
|
|
18
18
|
super(EditOrganizationPermission, self).__init__(need)
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class OrganizationPrivatePermission(Permission):
|
|
22
|
-
|
|
22
|
+
"""Permission to see organization private assets"""
|
|
23
|
+
|
|
23
24
|
def __init__(self, org):
|
|
24
25
|
super(OrganizationPrivatePermission, self).__init__(
|
|
25
|
-
OrganizationAdminNeed(org.id),
|
|
26
|
-
OrganizationEditorNeed(org.id)
|
|
26
|
+
OrganizationAdminNeed(org.id), OrganizationEditorNeed(org.id)
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
|
|
@@ -31,6 +31,5 @@ class OrganizationPrivatePermission(Permission):
|
|
|
31
31
|
def inject_organization_needs(sender, identity):
|
|
32
32
|
if current_user.is_authenticated:
|
|
33
33
|
for org in Organization.objects(members__user=current_user.id):
|
|
34
|
-
membership = get_by(org.members,
|
|
35
|
-
current_user._get_current_object())
|
|
34
|
+
membership = get_by(org.members, "user", current_user._get_current_object())
|
|
36
35
|
identity.provides.add(OrganizationNeed(membership.role, org.id))
|
udata/core/organization/rdf.py
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
2
|
This module centralize organization helpers
|
|
3
3
|
for RDF/DCAT serialization and parsing
|
|
4
|
-
|
|
4
|
+
"""
|
|
5
5
|
|
|
6
6
|
from flask import url_for
|
|
7
|
-
from rdflib import
|
|
8
|
-
from rdflib.namespace import RDF, RDFS
|
|
9
|
-
|
|
10
|
-
from udata.rdf import DCAT, DCT, namespace_manager, paginate_catalog
|
|
7
|
+
from rdflib import BNode, Graph, Literal, URIRef
|
|
8
|
+
from rdflib.namespace import FOAF, RDF, RDFS
|
|
11
9
|
|
|
12
10
|
from udata.core.dataset.rdf import dataset_to_rdf
|
|
13
|
-
from udata.
|
|
11
|
+
from udata.rdf import DCAT, DCT, namespace_manager, paginate_catalog
|
|
14
12
|
from udata.uris import endpoint_for
|
|
13
|
+
from udata.utils import Paginable
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def organization_to_rdf(org, graph=None):
|
|
18
|
-
|
|
17
|
+
"""
|
|
19
18
|
Map a Resource domain model to a DCAT/RDF graph
|
|
20
|
-
|
|
19
|
+
"""
|
|
21
20
|
graph = graph or Graph(namespace_manager=namespace_manager)
|
|
22
21
|
if org.id:
|
|
23
|
-
org_url = endpoint_for(
|
|
24
|
-
|
|
22
|
+
org_url = endpoint_for(
|
|
23
|
+
"organizations.show_redirect", "api.organization", org=org.id, _external=True
|
|
24
|
+
)
|
|
25
25
|
id = URIRef(org_url)
|
|
26
26
|
else:
|
|
27
27
|
id = BNode()
|
|
@@ -37,7 +37,7 @@ def organization_to_rdf(org, graph=None):
|
|
|
37
37
|
|
|
38
38
|
def build_org_catalog(org, datasets, format=None):
|
|
39
39
|
graph = Graph(namespace_manager=namespace_manager)
|
|
40
|
-
org_catalog_url = url_for(
|
|
40
|
+
org_catalog_url = url_for("api.organization_rdf", org=org.id, _external=True)
|
|
41
41
|
|
|
42
42
|
catalog = graph.resource(URIRef(org_catalog_url))
|
|
43
43
|
catalog.set(RDF.type, DCAT.Catalog)
|
|
@@ -48,9 +48,9 @@ def build_org_catalog(org, datasets, format=None):
|
|
|
48
48
|
for dataset in datasets:
|
|
49
49
|
catalog.add(DCAT.dataset, dataset_to_rdf(dataset, graph))
|
|
50
50
|
|
|
51
|
-
values = {
|
|
51
|
+
values = {"org": org.id}
|
|
52
52
|
|
|
53
53
|
if isinstance(datasets, Paginable):
|
|
54
|
-
paginate_catalog(catalog, graph, datasets, format,
|
|
54
|
+
paginate_catalog(catalog, graph, datasets, format, "api.organization_rdf_format", **values)
|
|
55
55
|
|
|
56
56
|
return catalog
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import datetime
|
|
2
|
+
|
|
2
3
|
from udata import search
|
|
4
|
+
from udata.core.organization.api import DEFAULT_SORTING, OrgApiParser
|
|
3
5
|
from udata.models import Organization
|
|
4
6
|
from udata.search.fields import Filter
|
|
5
|
-
from udata.core.organization.api import OrgApiParser, DEFAULT_SORTING
|
|
6
7
|
from udata.utils import to_iso_datetime
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
__all__ = ('OrganizationSearch', )
|
|
9
|
+
__all__ = ("OrganizationSearch",)
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@search.register
|
|
13
13
|
class OrganizationSearch(search.ModelSearchAdapter):
|
|
14
14
|
model = Organization
|
|
15
|
-
search_url =
|
|
15
|
+
search_url = "organizations/"
|
|
16
16
|
|
|
17
17
|
sorts = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
"reuses": "metrics.reuses",
|
|
19
|
+
"datasets": "metrics.datasets",
|
|
20
|
+
"followers": "metrics.followers",
|
|
21
|
+
"views": "metrics.views",
|
|
22
|
+
"created": "created_at",
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
filters = {
|
|
26
|
-
'badge': Filter()
|
|
27
|
-
}
|
|
25
|
+
filters = {"badge": Filter()}
|
|
28
26
|
|
|
29
27
|
@classmethod
|
|
30
28
|
def is_indexable(cls, org):
|
|
@@ -35,9 +33,13 @@ class OrganizationSearch(search.ModelSearchAdapter):
|
|
|
35
33
|
orgs = Organization.objects(deleted=None)
|
|
36
34
|
orgs = OrgApiParser.parse_filters(orgs, args)
|
|
37
35
|
|
|
38
|
-
sort =
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
sort = (
|
|
37
|
+
cls.parse_sort(args["sort"])
|
|
38
|
+
or ("$text_score" if args["q"] else None)
|
|
39
|
+
or DEFAULT_SORTING
|
|
40
|
+
)
|
|
41
|
+
offset = (args["page"] - 1) * args["page_size"]
|
|
42
|
+
return orgs.order_by(sort).skip(offset).limit(args["page_size"]), orgs.count()
|
|
41
43
|
|
|
42
44
|
@classmethod
|
|
43
45
|
def serialize(cls, organization):
|
|
@@ -45,17 +47,17 @@ class OrganizationSearch(search.ModelSearchAdapter):
|
|
|
45
47
|
for key, value in organization.extras.items():
|
|
46
48
|
extras[key] = to_iso_datetime(value) if isinstance(value, datetime.datetime) else value
|
|
47
49
|
return {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
"id": str(organization.id),
|
|
51
|
+
"name": organization.name,
|
|
52
|
+
"acronym": organization.acronym if organization.acronym else None,
|
|
53
|
+
"description": organization.description,
|
|
54
|
+
"url": organization.url,
|
|
55
|
+
"badges": [badge.kind for badge in organization.badges],
|
|
56
|
+
"created_at": to_iso_datetime(organization.created_at),
|
|
57
|
+
"orga_sp": 1 if organization.public_service else 0,
|
|
58
|
+
"followers": organization.metrics.get("followers", 0),
|
|
59
|
+
"datasets": organization.metrics.get("datasets", 0),
|
|
60
|
+
"reuses": organization.metrics.get("reuses", 0),
|
|
61
|
+
"views": organization.metrics.get("views", 0),
|
|
62
|
+
"extras": extras,
|
|
61
63
|
}
|