udata 10.6.1.dev36082__py2.py3-none-any.whl → 10.6.1.dev36098__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.
- udata/api/fields.py +0 -17
- udata/auth/views.py +22 -24
- udata/core/activity/api.py +1 -1
- udata/core/dataservices/api.py +3 -3
- udata/core/dataservices/models.py +11 -11
- udata/core/dataservices/rdf.py +3 -18
- udata/core/dataset/api.py +4 -3
- udata/core/dataset/api_fields.py +14 -25
- udata/core/dataset/apiv2.py +8 -11
- udata/core/dataset/csv.py +2 -2
- udata/core/dataset/models.py +18 -20
- udata/core/dataset/rdf.py +5 -38
- udata/core/dataset/search.py +1 -1
- udata/core/discussions/api.py +3 -1
- udata/core/discussions/models.py +11 -15
- udata/core/linkable.py +16 -0
- udata/core/organization/api.py +1 -0
- udata/core/organization/api_fields.py +14 -26
- udata/core/organization/csv.py +1 -1
- udata/core/organization/models.py +13 -16
- udata/core/organization/rdf.py +1 -5
- udata/core/post/api.py +8 -8
- udata/core/post/models.py +9 -16
- udata/core/reports/models.py +2 -2
- udata/core/reuse/api.py +4 -3
- udata/core/reuse/api_fields.py +1 -7
- udata/core/reuse/csv.py +1 -1
- udata/core/reuse/models.py +15 -22
- udata/core/site/rdf.py +2 -3
- udata/core/spatial/models.py +2 -9
- udata/core/topic/api.py +4 -8
- udata/core/topic/apiv2.py +3 -8
- udata/core/topic/models.py +0 -5
- udata/core/user/api_fields.py +14 -14
- udata/core/user/models.py +10 -16
- udata/core/user/rdf.py +1 -3
- udata/features/territories/models.py +1 -17
- udata/rdf.py +1 -2
- udata/routing.py +3 -2
- udata/settings.py +2 -0
- udata/static/chunks/{10.471164b2a9fe15614797.js → 10.8ca60413647062717b1e.js} +3 -3
- udata/static/chunks/{10.471164b2a9fe15614797.js.map → 10.8ca60413647062717b1e.js.map} +1 -1
- udata/static/chunks/{11.83535504cd650ea08f65.js → 11.0f04e49a40a0a381bcce.js} +3 -3
- udata/static/chunks/{11.83535504cd650ea08f65.js.map → 11.0f04e49a40a0a381bcce.js.map} +1 -1
- udata/static/chunks/{13.d9c1735d14038b94c17e.js → 13.f29411b06be1883356a3.js} +2 -2
- udata/static/chunks/{13.d9c1735d14038b94c17e.js.map → 13.f29411b06be1883356a3.js.map} +1 -1
- udata/static/chunks/{17.81c57c0dedf812e43013.js → 17.3bd0340930d4a314ce9c.js} +2 -2
- udata/static/chunks/{17.81c57c0dedf812e43013.js.map → 17.3bd0340930d4a314ce9c.js.map} +1 -1
- udata/static/chunks/{19.df16abde17a42033a7f8.js → 19.0586efa786ebf09fb288.js} +3 -3
- udata/static/chunks/{19.df16abde17a42033a7f8.js.map → 19.0586efa786ebf09fb288.js.map} +1 -1
- udata/static/chunks/{8.462bb3029de008497675.js → 8.b966402f5d680d4bdf4a.js} +2 -2
- udata/static/chunks/{8.462bb3029de008497675.js.map → 8.b966402f5d680d4bdf4a.js.map} +1 -1
- udata/static/chunks/{9.07515e5187f475bce828.js → 9.033d7e190ca9e226a5d0.js} +3 -3
- udata/static/chunks/{9.07515e5187f475bce828.js.map → 9.033d7e190ca9e226a5d0.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/templates/api/oauth_error.html +1 -1
- udata/templates/macros/metadata.html +0 -1
- udata/templates/mail/account_inactivity.html +1 -1
- udata/templates/mail/account_inactivity.txt +1 -1
- udata/templates/mail/badge_added_association.html +3 -3
- udata/templates/mail/badge_added_association.txt +1 -1
- udata/templates/mail/badge_added_certified.html +3 -3
- udata/templates/mail/badge_added_certified.txt +1 -1
- udata/templates/mail/badge_added_company.html +3 -3
- udata/templates/mail/badge_added_company.txt +1 -1
- udata/templates/mail/badge_added_local_authority.html +3 -3
- udata/templates/mail/badge_added_local_authority.txt +1 -1
- udata/templates/mail/badge_added_public_service.html +3 -3
- udata/templates/mail/badge_added_public_service.txt +1 -1
- udata/templates/mail/discussion_closed.html +3 -3
- udata/templates/mail/discussion_closed.txt +1 -1
- udata/templates/mail/frequency_reminder.html +1 -1
- udata/templates/mail/frequency_reminder.txt +1 -1
- udata/templates/mail/membership_refused.html +1 -1
- udata/templates/mail/membership_request.html +3 -3
- udata/templates/mail/membership_request.txt +1 -1
- udata/templates/mail/new_discussion.html +3 -3
- udata/templates/mail/new_discussion.txt +1 -1
- udata/templates/mail/new_discussion_comment.html +3 -3
- udata/templates/mail/new_discussion_comment.txt +1 -1
- udata/templates/mail/new_member.html +2 -2
- udata/templates/mail/new_member.txt +1 -1
- udata/templates/mail/new_reuse.html +2 -12
- udata/templates/mail/new_reuse.txt +1 -3
- udata/templates/mail/user_mail_card.html +1 -1
- udata/tests/api/test_dataservices_api.py +2 -2
- udata/tests/api/test_datasets_api.py +2 -2
- udata/tests/api/test_reuses_api.py +2 -2
- udata/tests/api/test_topics_api.py +4 -4
- udata/tests/dataset/test_dataset_rdf.py +1 -9
- udata/tests/test_discussions.py +3 -3
- udata/tests/test_mail.py +8 -0
- udata/uris.py +28 -7
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/METADATA +1 -1
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/RECORD +100 -99
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/LICENSE +0 -0
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/WHEEL +0 -0
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/entry_points.txt +0 -0
- {udata-10.6.1.dev36082.dist-info → udata-10.6.1.dev36098.dist-info}/top_level.txt +0 -0
udata/core/linkable.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Linkable:
|
|
2
|
+
def _link_id(self, **kwargs):
|
|
3
|
+
return self.id if kwargs.get("_useId", False) else self.slug
|
|
4
|
+
|
|
5
|
+
def _self_api_url_kwargs(self, **kwargs):
|
|
6
|
+
# Default to external
|
|
7
|
+
kwargs["_external"] = kwargs.pop("_external", True)
|
|
8
|
+
|
|
9
|
+
# Remove own private data
|
|
10
|
+
kwargs.pop("_useId", None)
|
|
11
|
+
kwargs.pop("_mailCampaign", None)
|
|
12
|
+
|
|
13
|
+
return kwargs
|
|
14
|
+
|
|
15
|
+
def url_for(self, **kwargs):
|
|
16
|
+
return self.self_web_url(**kwargs) or self.self_api_url(**kwargs)
|
udata/core/organization/api.py
CHANGED
|
@@ -13,21 +13,18 @@ org_ref_fields = api.inherit(
|
|
|
13
13
|
{
|
|
14
14
|
"name": fields.String(description="The organization name", readonly=True),
|
|
15
15
|
"acronym": fields.String(description="The organization acronym"),
|
|
16
|
-
"uri": fields.UrlFor(
|
|
17
|
-
"api.organization",
|
|
18
|
-
lambda o: {"org": o},
|
|
19
|
-
description="The organization API URI",
|
|
20
|
-
readonly=True,
|
|
21
|
-
),
|
|
22
16
|
"slug": fields.String(
|
|
23
17
|
description="The organization string used as permalink", required=True
|
|
24
18
|
),
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
"uri": fields.String(
|
|
20
|
+
attribute=lambda o: o.self_api_url(),
|
|
21
|
+
description="The API URI for this organization",
|
|
22
|
+
readonly=True,
|
|
23
|
+
),
|
|
24
|
+
"page": fields.String(
|
|
25
|
+
attribute=lambda o: o.self_web_url(),
|
|
28
26
|
description="The organization web page URL",
|
|
29
27
|
readonly=True,
|
|
30
|
-
fallback_endpoint="api.organization",
|
|
31
28
|
),
|
|
32
29
|
"logo": fields.ImageField(original=True, description="The organization logo URL"),
|
|
33
30
|
"logo_thumbnail": fields.ImageField(
|
|
@@ -151,18 +148,15 @@ org_fields = api.model(
|
|
|
151
148
|
description="The organization metrics",
|
|
152
149
|
readonly=True,
|
|
153
150
|
),
|
|
154
|
-
"uri": fields.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
description="The organization API URI",
|
|
151
|
+
"uri": fields.String(
|
|
152
|
+
attribute=lambda o: o.self_api_url(),
|
|
153
|
+
description="The API URI for this organization",
|
|
158
154
|
readonly=True,
|
|
159
155
|
),
|
|
160
|
-
"page": fields.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
description="The organization page URL",
|
|
156
|
+
"page": fields.String(
|
|
157
|
+
attribute=lambda o: o.self_web_url(),
|
|
158
|
+
description="The organization web page URL",
|
|
164
159
|
readonly=True,
|
|
165
|
-
fallback_endpoint="api.organization",
|
|
166
160
|
),
|
|
167
161
|
"logo": fields.ImageField(original=True, description="The organization logo URL"),
|
|
168
162
|
"logo_thumbnail": fields.ImageField(
|
|
@@ -211,12 +205,6 @@ org_suggestion_fields = api.model(
|
|
|
211
205
|
"image_url": fields.ImageField(
|
|
212
206
|
size=BIGGEST_LOGO_SIZE, description="The organization logo URL", readonly=True
|
|
213
207
|
),
|
|
214
|
-
"page": fields.
|
|
215
|
-
"organizations.show_redirect",
|
|
216
|
-
lambda o: {"org": o["slug"]},
|
|
217
|
-
description="The organization web page URL",
|
|
218
|
-
readonly=True,
|
|
219
|
-
fallback_endpoint="api.organization",
|
|
220
|
-
),
|
|
208
|
+
"page": fields.String(description="The organization web page URL", readonly=True),
|
|
221
209
|
},
|
|
222
210
|
)
|
udata/core/organization/csv.py
CHANGED
|
@@ -13,7 +13,7 @@ class OrganizationCsvAdapter(csv.Adapter):
|
|
|
13
13
|
"name",
|
|
14
14
|
"acronym",
|
|
15
15
|
"slug",
|
|
16
|
-
("url",
|
|
16
|
+
("url", lambda o: o.url_for()),
|
|
17
17
|
"description",
|
|
18
18
|
("logo", lambda o: o.logo(external=True)),
|
|
19
19
|
("badges", lambda o: ",".join([badge.kind for badge in o.badges])),
|
|
@@ -2,20 +2,21 @@ from datetime import datetime
|
|
|
2
2
|
from itertools import chain
|
|
3
3
|
|
|
4
4
|
from blinker import Signal
|
|
5
|
+
from flask import url_for
|
|
5
6
|
from mongoengine.signals import post_save, pre_save
|
|
6
7
|
from werkzeug.utils import cached_property
|
|
7
8
|
|
|
8
9
|
from udata.api_fields import field
|
|
9
10
|
from udata.core.activity.models import Auditable
|
|
10
11
|
from udata.core.badges.models import Badge, BadgeMixin, BadgesList
|
|
12
|
+
from udata.core.linkable import Linkable
|
|
11
13
|
from udata.core.metrics.helpers import get_stock_metrics
|
|
12
14
|
from udata.core.metrics.models import WithMetrics
|
|
13
15
|
from udata.core.storages import avatars, default_image_basename
|
|
14
16
|
from udata.frontend.markdown import mdstrip
|
|
15
17
|
from udata.i18n import lazy_gettext as _
|
|
16
|
-
from udata.mail import get_mail_campaign_dict
|
|
17
18
|
from udata.mongo import db
|
|
18
|
-
from udata.uris import
|
|
19
|
+
from udata.uris import cdata_url
|
|
19
20
|
|
|
20
21
|
from .constants import (
|
|
21
22
|
ASSOCIATION,
|
|
@@ -112,7 +113,9 @@ class OrganizationBadgeMixin(BadgeMixin):
|
|
|
112
113
|
__badges__ = BADGES
|
|
113
114
|
|
|
114
115
|
|
|
115
|
-
class Organization(
|
|
116
|
+
class Organization(
|
|
117
|
+
Auditable, WithMetrics, OrganizationBadgeMixin, Linkable, db.Datetimed, db.Document
|
|
118
|
+
):
|
|
116
119
|
name = field(db.StringField(required=True))
|
|
117
120
|
acronym = field(db.StringField(max_length=128))
|
|
118
121
|
slug = field(
|
|
@@ -189,19 +192,13 @@ class Organization(Auditable, WithMetrics, OrganizationBadgeMixin, db.Datetimed,
|
|
|
189
192
|
def pre_save(cls, sender, document, **kwargs):
|
|
190
193
|
cls.before_save.send(document)
|
|
191
194
|
|
|
192
|
-
def
|
|
193
|
-
return
|
|
195
|
+
def self_web_url(self, **kwargs):
|
|
196
|
+
return cdata_url(f"/organizations/{self._link_id(**kwargs)}/", **kwargs)
|
|
194
197
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return self.url_for(_external=True)
|
|
200
|
-
|
|
201
|
-
@property
|
|
202
|
-
def external_url_with_campaign(self):
|
|
203
|
-
extras = get_mail_campaign_dict()
|
|
204
|
-
return self.url_for(_external=True, **extras)
|
|
198
|
+
def self_api_url(self, **kwargs):
|
|
199
|
+
return url_for(
|
|
200
|
+
"api.organization", org=self._link_id(**kwargs), **self._self_api_url_kwargs(**kwargs)
|
|
201
|
+
)
|
|
205
202
|
|
|
206
203
|
@property
|
|
207
204
|
def pending_requests(self):
|
|
@@ -283,7 +280,7 @@ class Organization(Auditable, WithMetrics, OrganizationBadgeMixin, db.Datetimed,
|
|
|
283
280
|
"@type": type_,
|
|
284
281
|
"@id": str(self.id),
|
|
285
282
|
"alternateName": self.slug,
|
|
286
|
-
"url":
|
|
283
|
+
"url": self.url_for(),
|
|
287
284
|
"name": self.name,
|
|
288
285
|
"dateCreated": self.created_at.isoformat(),
|
|
289
286
|
"dateModified": self.last_modified.isoformat(),
|
udata/core/organization/rdf.py
CHANGED
|
@@ -10,7 +10,6 @@ from rdflib.namespace import FOAF, RDF, RDFS
|
|
|
10
10
|
from udata.core.dataservices.rdf import dataservice_to_rdf
|
|
11
11
|
from udata.core.dataset.rdf import dataset_to_rdf
|
|
12
12
|
from udata.rdf import DCAT, DCT, namespace_manager, paginate_catalog
|
|
13
|
-
from udata.uris import endpoint_for
|
|
14
13
|
from udata.utils import Paginable
|
|
15
14
|
|
|
16
15
|
|
|
@@ -20,10 +19,7 @@ def organization_to_rdf(org, graph=None):
|
|
|
20
19
|
"""
|
|
21
20
|
graph = graph or Graph(namespace_manager=namespace_manager)
|
|
22
21
|
if org.id:
|
|
23
|
-
|
|
24
|
-
"organizations.show_redirect", "api.organization", org=org.id, _external=True
|
|
25
|
-
)
|
|
26
|
-
id = URIRef(org_url)
|
|
22
|
+
id = URIRef(org.url_for(_useId=True))
|
|
27
23
|
else:
|
|
28
24
|
id = BNode()
|
|
29
25
|
o = graph.resource(id)
|
udata/core/post/api.py
CHANGED
|
@@ -48,15 +48,15 @@ post_fields = api.model(
|
|
|
48
48
|
),
|
|
49
49
|
"published": fields.ISODateTime(description="The post publication date", readonly=True),
|
|
50
50
|
"body_type": fields.String(description="HTML or markdown body type", default="markdown"),
|
|
51
|
-
"uri": fields.
|
|
52
|
-
|
|
51
|
+
"uri": fields.String(
|
|
52
|
+
attribute=lambda p: p.self_api_url(),
|
|
53
|
+
description="The API URI for this post",
|
|
54
|
+
readonly=True,
|
|
53
55
|
),
|
|
54
|
-
"page": fields.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
description="The post page URL",
|
|
56
|
+
"page": fields.String(
|
|
57
|
+
attribute=lambda p: p.self_web_url(),
|
|
58
|
+
description="The post web page URL",
|
|
58
59
|
readonly=True,
|
|
59
|
-
fallback_endpoint="api.post",
|
|
60
60
|
),
|
|
61
61
|
},
|
|
62
62
|
mask="*,datasets{id,title,acronym,uri,page},reuses{id,title,image,image_thumbnail,uri,page}",
|
|
@@ -130,7 +130,7 @@ class PostsAtomFeedAPI(API):
|
|
|
130
130
|
description=post.headline,
|
|
131
131
|
content=md(post.content),
|
|
132
132
|
author_name="data.gouv.fr",
|
|
133
|
-
link=post.
|
|
133
|
+
link=post.url_for(),
|
|
134
134
|
updateddate=post.last_modified,
|
|
135
135
|
pubdate=post.published,
|
|
136
136
|
)
|
udata/core/post/models.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from flask import url_for
|
|
2
2
|
|
|
3
|
+
from udata.core.linkable import Linkable
|
|
3
4
|
from udata.core.storages import default_image_basename, images
|
|
4
5
|
from udata.i18n import lazy_gettext as _
|
|
5
|
-
from udata.mail import get_mail_campaign_dict
|
|
6
6
|
from udata.mongo import db
|
|
7
|
+
from udata.uris import cdata_url
|
|
7
8
|
|
|
8
9
|
from .constants import BODY_TYPES, IMAGE_SIZES
|
|
9
10
|
|
|
@@ -15,7 +16,7 @@ class PostQuerySet(db.BaseQuerySet):
|
|
|
15
16
|
return self(published__ne=None).order_by("-published")
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class Post(db.Datetimed, db.Document):
|
|
19
|
+
class Post(db.Datetimed, Linkable, db.Document):
|
|
19
20
|
name = db.StringField(max_length=255, required=True)
|
|
20
21
|
slug = db.SlugField(
|
|
21
22
|
max_length=255, required=True, populate_from="name", update=True, follow=True
|
|
@@ -56,21 +57,13 @@ class Post(db.Datetimed, db.Document):
|
|
|
56
57
|
def __str__(self):
|
|
57
58
|
return self.name or ""
|
|
58
59
|
|
|
59
|
-
def
|
|
60
|
-
return
|
|
60
|
+
def self_web_url(self, **kwargs):
|
|
61
|
+
return cdata_url(f"/posts/{self._link_id(**kwargs)}/", **kwargs)
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@property
|
|
67
|
-
def external_url(self):
|
|
68
|
-
return self.url_for(_external=True)
|
|
69
|
-
|
|
70
|
-
@property
|
|
71
|
-
def external_url_with_campaign(self):
|
|
72
|
-
extras = get_mail_campaign_dict()
|
|
73
|
-
return self.url_for(_external=True, **extras)
|
|
63
|
+
def self_api_url(self, **kwargs):
|
|
64
|
+
return url_for(
|
|
65
|
+
"api.post", post=self._link_id(**kwargs), **self._self_api_url_kwargs(**kwargs)
|
|
66
|
+
)
|
|
74
67
|
|
|
75
68
|
def count_discussions(self):
|
|
76
69
|
# There are no metrics on Post to store discussions count
|
udata/core/reports/models.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
|
|
3
3
|
from bson import DBRef
|
|
4
|
+
from flask import url_for
|
|
4
5
|
from mongoengine import DO_NOTHING, NULLIFY, signals
|
|
5
6
|
|
|
6
7
|
from udata.api_fields import field, function_field, generate_fields
|
|
7
8
|
from udata.core.user.api_fields import user_ref_fields
|
|
8
9
|
from udata.core.user.models import User
|
|
9
10
|
from udata.mongo import db
|
|
10
|
-
from udata.uris import endpoint_for
|
|
11
11
|
|
|
12
12
|
from .constants import REPORT_REASONS_CHOICES, REPORTABLE_MODELS
|
|
13
13
|
|
|
@@ -48,7 +48,7 @@ class Report(db.Document):
|
|
|
48
48
|
|
|
49
49
|
@function_field(description="Link to the API endpoint for this report")
|
|
50
50
|
def self_api_url(self):
|
|
51
|
-
return
|
|
51
|
+
return url_for("api.report", report=self, _external=True)
|
|
52
52
|
|
|
53
53
|
@classmethod
|
|
54
54
|
def mark_as_deleted_soft_delete(cls, sender, document, **kwargs):
|
udata/core/reuse/api.py
CHANGED
|
@@ -150,10 +150,10 @@ class ReusesAtomFeedAPI(API):
|
|
|
150
150
|
author_uri = None
|
|
151
151
|
if reuse.organization:
|
|
152
152
|
author_name = reuse.organization.name
|
|
153
|
-
author_uri = reuse.organization.
|
|
153
|
+
author_uri = reuse.organization.url_for()
|
|
154
154
|
elif reuse.owner:
|
|
155
155
|
author_name = reuse.owner.fullname
|
|
156
|
-
author_uri = reuse.owner.
|
|
156
|
+
author_uri = reuse.owner.url_for()
|
|
157
157
|
feed.add_item(
|
|
158
158
|
reuse.title,
|
|
159
159
|
unique_id=reuse.id,
|
|
@@ -161,7 +161,7 @@ class ReusesAtomFeedAPI(API):
|
|
|
161
161
|
content=md(reuse.description),
|
|
162
162
|
author_name=author_name,
|
|
163
163
|
author_link=author_uri,
|
|
164
|
-
link=reuse.
|
|
164
|
+
link=reuse.url_for(),
|
|
165
165
|
updateddate=reuse.last_modified,
|
|
166
166
|
pubdate=reuse.created_at,
|
|
167
167
|
)
|
|
@@ -320,6 +320,7 @@ class ReusesSuggestAPI(API):
|
|
|
320
320
|
"title": reuse.title,
|
|
321
321
|
"slug": reuse.slug,
|
|
322
322
|
"image_url": reuse.image,
|
|
323
|
+
"page": reuse.self_web_url(),
|
|
323
324
|
}
|
|
324
325
|
for reuse in reuses.order_by(SUGGEST_SORTING).limit(args["size"])
|
|
325
326
|
]
|
udata/core/reuse/api_fields.py
CHANGED
|
@@ -30,13 +30,7 @@ reuse_suggestion_fields = api.model(
|
|
|
30
30
|
"image_url": fields.ImageField(
|
|
31
31
|
size=BIGGEST_IMAGE_SIZE, description="The reuse thumbnail URL", readonly=True
|
|
32
32
|
),
|
|
33
|
-
"page": fields.
|
|
34
|
-
"reuses.show_redirect",
|
|
35
|
-
lambda o: {"reuse": o["slug"]},
|
|
36
|
-
description="The reuse page URL",
|
|
37
|
-
readonly=True,
|
|
38
|
-
fallback_endpoint="api.reuse",
|
|
39
|
-
),
|
|
33
|
+
"page": fields.String(description="The reuse web page URL", readonly=True),
|
|
40
34
|
},
|
|
41
35
|
)
|
|
42
36
|
|
udata/core/reuse/csv.py
CHANGED
udata/core/reuse/models.py
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
from blinker import Signal
|
|
2
|
+
from flask import url_for
|
|
2
3
|
from mongoengine.signals import post_save, pre_save
|
|
3
4
|
from werkzeug.utils import cached_property
|
|
4
5
|
|
|
5
6
|
from udata.api_fields import field, function_field, generate_fields
|
|
6
7
|
from udata.core.activity.models import Auditable
|
|
7
8
|
from udata.core.dataset.api_fields import dataset_fields
|
|
9
|
+
from udata.core.linkable import Linkable
|
|
8
10
|
from udata.core.metrics.helpers import get_stock_metrics
|
|
9
11
|
from udata.core.owned import Owned, OwnedQuerySet
|
|
10
12
|
from udata.core.reuse.api_fields import BIGGEST_IMAGE_SIZE, reuse_permissions_fields
|
|
11
13
|
from udata.core.storages import default_image_basename, images
|
|
12
14
|
from udata.frontend.markdown import mdstrip
|
|
13
15
|
from udata.i18n import lazy_gettext as _
|
|
14
|
-
from udata.mail import get_mail_campaign_dict
|
|
15
16
|
from udata.models import Badge, BadgeMixin, BadgesList, WithMetrics, db
|
|
16
17
|
from udata.mongo.errors import FieldValidationError
|
|
17
|
-
from udata.uris import
|
|
18
|
+
from udata.uris import cdata_url
|
|
18
19
|
from udata.utils import hash_url
|
|
19
20
|
|
|
20
21
|
from .constants import IMAGE_MAX_SIZE, IMAGE_SIZES, REUSE_TOPICS, REUSE_TYPES
|
|
@@ -62,7 +63,7 @@ class ReuseBadgeMixin(BadgeMixin):
|
|
|
62
63
|
additional_filters={"organization_badge": "organization.badges"},
|
|
63
64
|
mask="*,datasets{id,title,uri,page}",
|
|
64
65
|
)
|
|
65
|
-
class Reuse(db.Datetimed, Auditable, WithMetrics, ReuseBadgeMixin, Owned, db.Document):
|
|
66
|
+
class Reuse(db.Datetimed, Auditable, WithMetrics, ReuseBadgeMixin, Linkable, Owned, db.Document):
|
|
66
67
|
title = field(
|
|
67
68
|
db.StringField(required=True),
|
|
68
69
|
sortable=True,
|
|
@@ -187,20 +188,21 @@ class Reuse(db.Datetimed, Auditable, WithMetrics, ReuseBadgeMixin, Owned, db.Doc
|
|
|
187
188
|
# Emit before_save
|
|
188
189
|
cls.before_save.send(document)
|
|
189
190
|
|
|
190
|
-
def
|
|
191
|
-
return
|
|
191
|
+
def self_web_url(self, **kwargs):
|
|
192
|
+
return cdata_url(f"/reuses/{self._link_id(**kwargs)}/", **kwargs)
|
|
192
193
|
|
|
193
|
-
|
|
194
|
+
def self_api_url(self, **kwargs):
|
|
195
|
+
return url_for(
|
|
196
|
+
"api.reuse", reuse=self._link_id(**kwargs), **self._self_api_url_kwargs(**kwargs)
|
|
197
|
+
)
|
|
194
198
|
|
|
195
199
|
@function_field(description="Link to the API endpoint for this reuse", show_as_ref=True)
|
|
196
|
-
def uri(self):
|
|
197
|
-
return
|
|
200
|
+
def uri(self, *args, **kwargs):
|
|
201
|
+
return self.self_api_url(*args, **kwargs)
|
|
198
202
|
|
|
199
203
|
@function_field(description="Link to the udata web page for this reuse", show_as_ref=True)
|
|
200
|
-
def page(self):
|
|
201
|
-
return
|
|
202
|
-
"reuses.show", reuse=self, _external=True, fallback_endpoint="api.reuse"
|
|
203
|
-
)
|
|
204
|
+
def page(self, *args, **kwargs):
|
|
205
|
+
return self.self_web_url(*args, **kwargs)
|
|
204
206
|
|
|
205
207
|
@property
|
|
206
208
|
@function_field(
|
|
@@ -222,15 +224,6 @@ class Reuse(db.Datetimed, Auditable, WithMetrics, ReuseBadgeMixin, Owned, db.Doc
|
|
|
222
224
|
def is_hidden(self):
|
|
223
225
|
return len(self.datasets) == 0 or self.private or self.deleted
|
|
224
226
|
|
|
225
|
-
@property
|
|
226
|
-
def external_url(self):
|
|
227
|
-
return self.url_for(_external=True)
|
|
228
|
-
|
|
229
|
-
@property
|
|
230
|
-
def external_url_with_campaign(self):
|
|
231
|
-
extras = get_mail_campaign_dict()
|
|
232
|
-
return self.url_for(_external=True, **extras)
|
|
233
|
-
|
|
234
227
|
@property
|
|
235
228
|
def type_label(self):
|
|
236
229
|
return REUSE_TYPES[self.type]
|
|
@@ -263,7 +256,7 @@ class Reuse(db.Datetimed, Auditable, WithMetrics, ReuseBadgeMixin, Owned, db.Doc
|
|
|
263
256
|
"alternateName": self.slug,
|
|
264
257
|
"dateCreated": self.created_at.isoformat(),
|
|
265
258
|
"dateModified": self.last_modified.isoformat(),
|
|
266
|
-
"url":
|
|
259
|
+
"url": self.url_for(),
|
|
267
260
|
"name": self.title,
|
|
268
261
|
"isBasedOnUrl": self.url,
|
|
269
262
|
}
|
udata/core/site/rdf.py
CHANGED
|
@@ -11,13 +11,12 @@ from udata.core.dataset.rdf import dataset_to_rdf
|
|
|
11
11
|
from udata.core.organization.rdf import organization_to_rdf
|
|
12
12
|
from udata.core.user.rdf import user_to_rdf
|
|
13
13
|
from udata.rdf import DCAT, DCT, namespace_manager, paginate_catalog
|
|
14
|
-
from udata.uris import
|
|
14
|
+
from udata.uris import homepage_url
|
|
15
15
|
from udata.utils import Paginable
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def build_catalog(site, datasets, dataservices=[], format=None):
|
|
19
19
|
"""Build the DCAT catalog for this site"""
|
|
20
|
-
site_url = endpoint_for("site.home_redirect", "api.site", _external=True)
|
|
21
20
|
catalog_url = url_for("api.site_rdf_catalog", _external=True)
|
|
22
21
|
graph = Graph(namespace_manager=namespace_manager)
|
|
23
22
|
catalog = graph.resource(URIRef(catalog_url))
|
|
@@ -26,7 +25,7 @@ def build_catalog(site, datasets, dataservices=[], format=None):
|
|
|
26
25
|
catalog.set(DCT.title, Literal(site.title))
|
|
27
26
|
catalog.set(DCT.description, Literal(f"{site.title}"))
|
|
28
27
|
catalog.set(DCT.language, Literal(current_app.config["DEFAULT_LANGUAGE"]))
|
|
29
|
-
catalog.set(FOAF.homepage, URIRef(
|
|
28
|
+
catalog.set(FOAF.homepage, URIRef(homepage_url(_external=True)))
|
|
30
29
|
|
|
31
30
|
publisher = graph.resource(BNode())
|
|
32
31
|
publisher.set(RDF.type, FOAF.Organization)
|
udata/core/spatial/models.py
CHANGED
|
@@ -6,9 +6,7 @@ from werkzeug.utils import cached_property
|
|
|
6
6
|
from udata.app import cache
|
|
7
7
|
from udata.core.metrics.models import WithMetrics
|
|
8
8
|
from udata.i18n import _, get_locale, language
|
|
9
|
-
from udata.mail import get_mail_campaign_dict
|
|
10
9
|
from udata.mongo import db
|
|
11
|
-
from udata.uris import endpoint_for
|
|
12
10
|
|
|
13
11
|
from . import geoids
|
|
14
12
|
from .constants import ADMIN_LEVEL_MAX, ADMIN_LEVEL_MIN, BASE_GRANULARITIES
|
|
@@ -93,16 +91,11 @@ class GeoZone(WithMetrics, db.Document):
|
|
|
93
91
|
|
|
94
92
|
@property
|
|
95
93
|
def url(self):
|
|
96
|
-
return
|
|
94
|
+
return None
|
|
97
95
|
|
|
98
96
|
@property
|
|
99
97
|
def external_url(self):
|
|
100
|
-
return
|
|
101
|
-
|
|
102
|
-
@property
|
|
103
|
-
def external_url_with_campaign(self):
|
|
104
|
-
extras = get_mail_campaign_dict()
|
|
105
|
-
return endpoint_for("territories.territory", territory=self, _external=True, **extras)
|
|
98
|
+
return None
|
|
106
99
|
|
|
107
100
|
def count_datasets(self):
|
|
108
101
|
from udata.models import Dataset
|
udata/core/topic/api.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import mongoengine
|
|
2
|
+
from flask import url_for
|
|
2
3
|
from flask_security import current_user
|
|
3
4
|
|
|
4
5
|
from udata.api import API, api, fields
|
|
@@ -58,15 +59,10 @@ topic_fields = api.model(
|
|
|
58
59
|
"owner": fields.Nested(
|
|
59
60
|
user_ref_fields, description="The owner user", readonly=True, allow_null=True
|
|
60
61
|
),
|
|
61
|
-
"uri": fields.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"page": fields.UrlFor(
|
|
65
|
-
"topics.display",
|
|
66
|
-
lambda o: {"topic": o},
|
|
67
|
-
description="The topic page URL",
|
|
62
|
+
"uri": fields.String(
|
|
63
|
+
attribute=lambda t: url_for("api.topic", topic=t),
|
|
64
|
+
description="The topic API URI",
|
|
68
65
|
readonly=True,
|
|
69
|
-
fallback_endpoint="api.topic",
|
|
70
66
|
),
|
|
71
67
|
"extras": fields.Raw(description="Extras attributes as key-value pairs"),
|
|
72
68
|
},
|
udata/core/topic/apiv2.py
CHANGED
|
@@ -93,15 +93,10 @@ topic_fields = apiv2.model(
|
|
|
93
93
|
"owner": fields.Nested(
|
|
94
94
|
user_ref_fields, description="The owner user", readonly=True, allow_null=True
|
|
95
95
|
),
|
|
96
|
-
"uri": fields.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"page": fields.UrlFor(
|
|
100
|
-
"topics.display",
|
|
101
|
-
lambda o: {"topic": o},
|
|
102
|
-
description="The topic page URL",
|
|
96
|
+
"uri": fields.String(
|
|
97
|
+
attribute=lambda t: url_for("api.topic", topic=t),
|
|
98
|
+
description="The topic API URI",
|
|
103
99
|
readonly=True,
|
|
104
|
-
fallback_endpoint="api.topic",
|
|
105
100
|
),
|
|
106
101
|
"extras": fields.Raw(description="Extras attributes as key-value pairs"),
|
|
107
102
|
},
|
udata/core/topic/models.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from blinker import Signal
|
|
2
|
-
from flask import url_for
|
|
3
2
|
from mongoengine.signals import post_save, pre_save
|
|
4
3
|
|
|
5
4
|
from udata.api_fields import field
|
|
@@ -57,10 +56,6 @@ class Topic(db.Datetimed, Auditable, db.Document, Owned):
|
|
|
57
56
|
for dataset in datasets_list_dif:
|
|
58
57
|
reindex.delay("Dataset", str(dataset.pk))
|
|
59
58
|
|
|
60
|
-
@property
|
|
61
|
-
def display_url(self):
|
|
62
|
-
return url_for("topics.display", topic=self)
|
|
63
|
-
|
|
64
59
|
def count_discussions(self):
|
|
65
60
|
# There are no metrics on Topic to store discussions count
|
|
66
61
|
pass
|
udata/core/user/api_fields.py
CHANGED
|
@@ -10,15 +10,15 @@ user_ref_fields = api.inherit(
|
|
|
10
10
|
"first_name": fields.String(description="The user first name", readonly=True),
|
|
11
11
|
"last_name": fields.String(description="The user larst name", readonly=True),
|
|
12
12
|
"slug": fields.String(description="The user permalink string", required=True),
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
description="The user profile page URL",
|
|
13
|
+
"uri": fields.String(
|
|
14
|
+
attribute=lambda u: u.self_api_url(),
|
|
15
|
+
description="The API URI for this user",
|
|
17
16
|
readonly=True,
|
|
18
|
-
fallback_endpoint="api.user",
|
|
19
17
|
),
|
|
20
|
-
"
|
|
21
|
-
|
|
18
|
+
"page": fields.String(
|
|
19
|
+
attribute=lambda u: u.self_web_url(),
|
|
20
|
+
description="The user web page URL",
|
|
21
|
+
readonly=True,
|
|
22
22
|
),
|
|
23
23
|
"avatar": fields.ImageField(original=True, description="The user avatar URL"),
|
|
24
24
|
"avatar_thumbnail": fields.ImageField(
|
|
@@ -66,15 +66,15 @@ user_fields = api.model(
|
|
|
66
66
|
description="The user last connection date (only present for global admins and on /me)",
|
|
67
67
|
readonly=True,
|
|
68
68
|
),
|
|
69
|
-
"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
description="The user profile page URL",
|
|
69
|
+
"uri": fields.String(
|
|
70
|
+
attribute=lambda u: u.self_api_url(),
|
|
71
|
+
description="The API URI for this user",
|
|
73
72
|
readonly=True,
|
|
74
|
-
fallback_endpoint="api.user",
|
|
75
73
|
),
|
|
76
|
-
"
|
|
77
|
-
|
|
74
|
+
"page": fields.String(
|
|
75
|
+
attribute=lambda u: u.self_web_url(),
|
|
76
|
+
description="The user web page URL",
|
|
77
|
+
readonly=True,
|
|
78
78
|
),
|
|
79
79
|
"metrics": fields.Raw(
|
|
80
80
|
attribute=lambda o: o.get_metrics(), description="The user metrics", readonly=True
|