Repository: akvo/akvo-rsr

Issue:
RSR API - allow more than 1 parameter
## Test plan

The example queries in the doc string of filters.py are good examples of queries that should work and return objects (the domain part needs changing of course). I can help construct other more complex examples if needed. One possibility is to construct queries that return the same result as long as the objects in the result set aren't changed that could then be used in the integration/web tests (I'm not sure about the current status of our testing suite). This could be existing project updates for instance, they are pretty stable I'd say.

To test the select_related and prefetch_related functionality is harder. For that you really need to analyze the queries executed with and without them included on sufficiently complex queries, and I don't know if we have that functionality in place right now. Django-debug-toolbar can tell you how many queries a view generates, and I think you can get it to work with DRF.
## Issue description

Akvo Sites partners are currently in need of the more flexibility when it comes to pulling information to their sites from RSR. 

Currently you cannot filter project updates to be read by 'project_partnerships_organisation' AND 'keywords' (for example).

Use case:
Akvo Site, drydev.org
Akvo Data Feed plugin currently uses the RSR API to read, then display in widgets, all project updates for 'project_partnerships_organisation=415'  
Unfortunately, not all of the projects for  'project_partnerships_organisation=415'   have anything to do with the 'DryDev' project they have the site for.
They would like to filter that data by the keyword used on the projects ie. 'drydev'.

This can currently not be done, the ability to add additional parameters for reading data via the API is required.



Discussion:
Just had a chat with @zzgvh during the RSR stand-up, and he'll be looking into it.

If a quick solution is needed now, you would need multiple API calls to get this done:
- http://rsr.akvo.org/rest/v1/project/?keywords=119 for the projects (returns 4 projects)
- For each of the projects: http://rsr.akvo.org/rest/v1/project_update/?project=(project_id)

Thanks guys.  The quick solution would mean re-coding the JSON data feed plugin to allow the correct data to then be filtered from the read data & displayed in the widget.  Not sure this is worthwhile if the RSR API needs to provide this ability anyway.

Added a small demo/experiment. It's simple, but basically gets the job done. There's stuff needed if we're to use it in production, but I think the core idea of just adding an interface to the Django ORM query language is good. And since you can only filter I can't see that it's any security problems around it.

Additional info on why I built the demo. I've looked at a package called django-rest-framework-filters, which is nice since it allows you to do ORM-style filtering "directly" in the query string, e.g. `/api/page/?author__username__icontains=john`. But the problem is that you still have to code all variants of filters you want to support. It might be possible to "automate" this, but I don't know if it's worth the effort for what is essentially a cosmetic improvement of the way the query string ends up looking. Using my solution the filter above would look like this: `/api/page/?filter=author__username__icontains=john` so the difference isn't that large.

Using the new version of the RSRGenericFilterBackend, the query to solve the original problem would be:

```
http://rsr.localdev.akvo.org/rest/v1/project_update/?filter={'project__partners':415,'project__keywords__label':'drydev'}
```

and could be extended with related models: 

```
http://rsr.localdev.akvo.org/rest/v1/project_update/?filter={'project__partners':415,'project__keywords__label':'drydev'}&select_related=['project']&prefetch_related=['project__keywords']
```

Closed in #2116


Resolving patch:
diff --git a/akvo/rest/viewsets.py b/akvo/rest/viewsets.py
--- a/akvo/rest/viewsets.py
+++ b/akvo/rest/viewsets.py
@@ -42,8 +42,9 @@ def django_filter_filters(request):
             """
             # query string keys reserved by the RSRGenericFilterBackend
             qs_params = ['filter', 'exclude', 'select_related', 'prefetch_related', ]
-            # query string keys used by core DRF and OrderingFilter
-            exclude_params = ['limit', 'format', 'page', 'ordering', ]
+            # query string keys used by core DRF, OrderingFilter and Akvo custom views
+            exclude_params = ['limit', 'format', 'page', 'ordering', 'partner_type', 'sync_owner',
+                              'reporting_org']
             filters = {}
             for key in request.QUERY_PARAMS.keys():
                 if key not in qs_params + exclude_params:


Test patch: