From 97934d0e74a15969673340fd7d23ed834fd2c823 Mon Sep 17 00:00:00 2001 From: Tobias Megies Date: Mon, 2 May 2016 18:01:51 +0200 Subject: [PATCH] introduce an option to negate the filtering on a queryset i.e. make the filter not return events that match all given criteria, but rather return events, that do not match the combination of given criteria. otherwise it is impossible to define a retrieve permission for a combination of two criteria (i.e. when user "does not have permission" to exclude events that match the given combination of criteria, e.g. exclude events at site X and below magnitude Y) --- src/jane/documents/models.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/jane/documents/models.py b/src/jane/documents/models.py index 0cc1635..63d649e 100644 --- a/src/jane/documents/models.py +++ b/src/jane/documents/models.py @@ -320,7 +320,7 @@ def get_filtered_queryset_radial_distance( Distance(km=deg2km(max_radius)))) return queryset - def get_filtered_queryset(self, document_type, queryset=None, + def get_filtered_queryset(self, document_type, queryset=None, negate=False, **kwargs): """ Returns a queryset filtered on the items in the JSON document. @@ -329,6 +329,12 @@ def get_filtered_queryset(self, document_type, queryset=None, queryset is passed. :param queryset: If no queryset is passed, a new one will be created, otherwise an existing one will be used and filtered. + :type negate: bool + :param negate: When ``negate=True`` then the resulting queryset is + inverted, i.e. the resulting queryset returns all events that do + not match all given criteria. For example, ``.., negate=True, + max_magnitude=1, site="unterhaching")`` returns all events except + events at site Unterhaching that are below magnitude 1. :param kwargs: Any additional query parameters. Assuming a key named ``"example"`` in the JSON file you can search @@ -362,6 +368,12 @@ def get_filtered_queryset(self, document_type, queryset=None, ``public=True`` ``kwargs={"!public": True}`` + The resulting query set can be inverted with ``negate=True``:: + + * For example, using ``.., negate=True, max_magnitude=1, + site="unterhaching")`` returns all events except for events that are + both declared at site Unterhaching and below magnitude 1. + Please note that as soon as you search for a value, all values that are null will be discarded from the queryset (even if you search for !=)! This might be changed in the future. @@ -448,6 +460,11 @@ def get_filtered_queryset(self, document_type, queryset=None, else: raise NotImplementedError() + # if "negate" option is selected: instead of filtering to given + # criteria, filter out all items that match given criteria + if where != [] and negate: + where = ["NOT ({})".format(" AND ".join(where))] + queryset = queryset.extra(where=where) if "ordering" in kwargs and kwargs["ordering"] in meta: