0001-opendatasoft-add-sort-field-54442.patch
passerelle/apps/opendatasoft/migrations/0003_query_sort.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.29 on 2021-06-25 17:01 |
|
3 |
from __future__ import unicode_literals |
|
4 | ||
5 |
from django.db import migrations, models |
|
6 | ||
7 | ||
8 |
class Migration(migrations.Migration): |
|
9 | ||
10 |
dependencies = [ |
|
11 |
('opendatasoft', '0002_auto_20210625_1852'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.AddField( |
|
16 |
model_name='query', |
|
17 |
name='sort', |
|
18 |
field=models.CharField( |
|
19 |
blank=True, |
|
20 |
help_text='Sorts results by the specified field. A minus sign - may be used to perform an ascending sort.', |
|
21 |
max_length=256, |
|
22 |
verbose_name='Sort field', |
|
23 |
), |
|
24 |
), |
|
25 |
] |
passerelle/apps/opendatasoft/models.py | ||
---|---|---|
59 | 59 |
Query.objects.filter(resource=instance).delete() |
60 | 60 |
for data_query in data_queries: |
61 | 61 |
query = Query.import_json(data_query) |
62 | 62 |
query.resource = instance |
63 | 63 |
queries.append(query) |
64 | 64 |
Query.objects.bulk_create(queries) |
65 | 65 |
return instance |
66 | 66 | |
67 |
def call_search(self, dataset=None, text_template='', filter_expression='', id=None, q=None, limit=None): |
|
67 |
def call_search( |
|
68 |
self, dataset=None, text_template='', filter_expression='', sort='', id=None, q=None, limit=None |
|
69 |
): |
|
68 | 70 |
scheme, netloc, path, params, query, fragment = urlparse.urlparse(self.service_url) |
69 | 71 |
path = urlparse.urljoin(path, 'api/records/1.0/search/') |
70 | 72 |
url = urlparse.urlunparse((scheme, netloc, path, params, query, fragment)) |
71 | 73 | |
72 | 74 |
if id is not None: |
73 | 75 |
query = 'recordid:%s' % id |
74 | 76 |
else: |
75 | 77 |
query = q |
76 | 78 |
params = { |
77 | 79 |
'dataset': dataset, |
78 | 80 |
'q': query, |
79 | 81 |
} |
80 | 82 |
if self.api_key: |
81 | 83 |
params.update({'apikey': self.api_key}) |
82 | 84 |
if limit: |
83 | 85 |
params.update({'rows': limit}) |
86 |
if sort: |
|
87 |
params.update({'sort': sort}) |
|
84 | 88 |
params.update(urlparse.parse_qs(filter_expression)) |
85 | 89 | |
86 | 90 |
result_response = self.requests.get(url, params=params) |
87 | 91 |
err_desc = result_response.json().get('error') |
88 | 92 |
if err_desc: |
89 | 93 |
raise APIError(err_desc, http_status=200) |
90 | 94 | |
91 | 95 |
result = [] |
... | ... | |
146 | 150 |
validators=[validate_template], |
147 | 151 |
blank=True, |
148 | 152 |
) |
149 | 153 |
filter_expression = models.TextField( |
150 | 154 |
verbose_name=_('filter'), |
151 | 155 |
help_text=_('Specify refine and exclude facet expressions separated lines'), |
152 | 156 |
blank=True, |
153 | 157 |
) |
158 |
sort = models.CharField( |
|
159 |
verbose_name=_('Sort field'), |
|
160 |
help_text=_( |
|
161 |
"Sorts results by the specified field. A minus sign - may be used to perform an ascending sort." |
|
162 |
), |
|
163 |
max_length=256, |
|
164 |
blank=True, |
|
165 |
) |
|
154 | 166 | |
155 | 167 |
delete_view = 'opendatasoft-query-delete' |
156 | 168 |
edit_view = 'opendatasoft-query-edit' |
157 | 169 | |
158 | 170 |
def q(self, request, **kwargs): |
159 | 171 |
return self.resource.call_search( |
160 | 172 |
dataset=self.dataset, |
161 | 173 |
text_template=self.text_template, |
162 | 174 |
filter_expression='&'.join( |
163 | 175 |
[x.strip() for x in str(self.filter_expression).splitlines() if x.strip()] |
164 | 176 |
), |
177 |
sort=self.sort, |
|
165 | 178 |
id=kwargs.get('id'), |
166 | 179 |
q=kwargs.get('q'), |
167 | 180 |
limit=kwargs.get('limit'), |
168 | 181 |
) |
169 | 182 | |
170 | 183 |
def as_endpoint(self): |
171 | 184 |
endpoint = super(Query, self).as_endpoint(path=self.resource.q.endpoint_info.name) |
172 | 185 |
tests/test_opendatasoft.py | ||
---|---|---|
138 | 138 |
def query(connector): |
139 | 139 |
return Query.objects.create( |
140 | 140 |
resource=connector, |
141 | 141 |
name='Référenciel adresses de test', |
142 | 142 |
slug='my_query', |
143 | 143 |
description='Rechercher une adresse', |
144 | 144 |
dataset='referentiel-adresse-test', |
145 | 145 |
text_template='{{numero}} {{nom_rue}} {{nom_commun}}', |
146 |
sort='-nom_rue', |
|
146 | 147 |
filter_expression=''' |
147 | 148 |
refine.source=Ville et Eurométropole de Strasbourg |
148 | 149 |
exclude.numero=42 |
149 | 150 |
exclude.numero=43 |
150 | 151 |
''', |
151 | 152 |
) |
152 | 153 | |
153 | 154 | |
... | ... | |
244 | 245 |
resp = app.get(endpoint, params=params, status=200) |
245 | 246 |
assert mocked_get.call_args[1]['params'] == { |
246 | 247 |
'dataset': 'referentiel-adresse-test', |
247 | 248 |
'q': "rue de l'aubepine", |
248 | 249 |
'apikey': 'my_secret', |
249 | 250 |
'rows': '3', |
250 | 251 |
'refine.source': ['Ville et Eurométropole de Strasbourg'], |
251 | 252 |
'exclude.numero': ['42', '43'], |
253 |
'sort': '-nom_rue', |
|
252 | 254 |
} |
253 | 255 |
assert not resp.json['err'] |
254 | 256 |
assert len(resp.json['data']) == 3 |
255 | 257 |
# check order is kept |
256 | 258 |
assert [x['id'] for x in resp.json['data']] == [ |
257 | 259 |
'e00cf6161e52a4c8fe510b2b74d4952036cb3473', |
258 | 260 |
'7cafcd5c692773e8b863587b2d38d6be82e023d8', |
259 | 261 |
'0984a5e1745701f71c91af73ce764e1f7132e0ff', |
... | ... | |
277 | 279 |
mocked_get.return_value = utils.FakedResponse(content=FAKED_CONTENT_ID_SEARCH, status_code=200) |
278 | 280 |
resp = app.get(endpoint, params=params, status=200) |
279 | 281 |
assert mocked_get.call_args[1]['params'] == { |
280 | 282 |
'dataset': 'referentiel-adresse-test', |
281 | 283 |
'q': 'recordid:7cafcd5c692773e8b863587b2d38d6be82e023d8', |
282 | 284 |
'apikey': 'my_secret', |
283 | 285 |
'refine.source': ['Ville et Eurométropole de Strasbourg'], |
284 | 286 |
'exclude.numero': ['42', '43'], |
287 |
'sort': '-nom_rue', |
|
285 | 288 |
} |
286 | 289 |
assert len(resp.json['data']) == 1 |
287 | 290 |
assert resp.json['data'][0]['text'] == "19 RUE DE L'AUBEPINE Lipsheim" |
288 | 291 | |
289 | 292 | |
290 | 293 |
def test_opendatasoft_query_unicity(admin_user, app, connector, query): |
291 | 294 |
connector2 = OpenDataSoft.objects.create( |
292 | 295 |
slug='my_connector2', |
293 |
- |