Projet

Général

Profil

0001-opendatasoft-add-sort-field-54442.patch

Nicolas Roche, 25 juin 2021 19:43

Télécharger (6,67 ko)

Voir les différences:

Subject: [PATCH] opendatasoft: add sort field (#54442)

 .../migrations/0003_query_sort.py             | 25 +++++++++++++++++++
 passerelle/apps/opendatasoft/models.py        | 15 ++++++++++-
 tests/test_opendatasoft.py                    |  3 +++
 3 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 passerelle/apps/opendatasoft/migrations/0003_query_sort.py
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
-