diff --git a/graphene_django/elasticsearch/filter/filters.py b/graphene_django/elasticsearch/filter/filters.py index 4044a99..2c55785 100644 --- a/graphene_django/elasticsearch/filter/filters.py +++ b/graphene_django/elasticsearch/filter/filters.py @@ -51,13 +51,12 @@ class FilterES(object): processor_class = PROCESSORS[variant] return processor_class(self, self.processor) - def generate_es_query(self, arguments): + def attach_processor(self, observer): """ Generating a query based on the arguments passed to graphene field - :param arguments: parameters of the query. - :return: Returns a elasticsearch_dsl.Q query object. + :param observer: observer to attach the processors. """ - return self.processor.generate_es_query(arguments) + return self.processor.to_attach(observer) class StringFilterES(FilterES): diff --git a/graphene_django/elasticsearch/filter/filterset.py b/graphene_django/elasticsearch/filter/filterset.py index aa4ae4b..83fbd2a 100644 --- a/graphene_django/elasticsearch/filter/filterset.py +++ b/graphene_django/elasticsearch/filter/filterset.py @@ -10,6 +10,7 @@ from django.utils import six from django_filters.utils import try_dbfield from django_filters.filterset import BaseFilterSet +from graphene_django.elasticsearch.filter.observable import FieldResolverObservable from .filters import StringFilterES, FilterES, BoolFilterES, NumberFilterES # Basic conversion from ES fields to FilterES fields @@ -153,12 +154,13 @@ class FilterSetESMetaclass(type): meta_filters = mcs.get_meta_filters(new_class._meta) declared_filters.update(meta_filters) - new_class.filters_es = declared_filters - # recollecting registered graphene fields + # recollecting registered graphene fields and attaching to observable base_filters = OrderedDict() + observable = FieldResolverObservable() for filter_name, filter_field in six.iteritems(declared_filters): base_filters.update(filter_field.fields) + filter_field.attach_processor(observable) # adding sort field sort_fields = {} @@ -169,6 +171,7 @@ class FilterSetESMetaclass(type): new_class.sort_fields = sort_fields new_class.base_filters = base_filters + new_class.observable = observable return new_class @@ -380,13 +383,13 @@ class FilterSetES(six.with_metaclass(FilterSetESMetaclass, object)): # if the query have data if len(self.data): # for each field passed to the query - for name, filter in six.iteritems(self.filters_es): - # If a target filter is en FilterEs - if isinstance(filter, FilterES): - # It is generated a query or response None if the filter don't have data - query_filter = filter.generate_es_query(self.data) + for name, value in six.iteritems(self.data): + # ignore sort field + if name == "sort": + continue - if query_filter is not None: - query_base += query_filter + # dispatch observable resolve + resolve = self.observable.resolve(name, value) + query_base += resolve return query_base diff --git a/graphene_django/elasticsearch/filter/observable.py b/graphene_django/elasticsearch/filter/observable.py new file mode 100644 index 0000000..d4273eb --- /dev/null +++ b/graphene_django/elasticsearch/filter/observable.py @@ -0,0 +1,18 @@ + +class FieldResolverObservable(object): + """Observable to attach processor by field and resolve it with the field value""" + + def __init__(self): + """A new Observable by filterset""" + super(FieldResolverObservable).__init__() + self._fields = {} + + def attach(self, field, processor): + """Add processor to fields""" + self._fields[field] = processor + + def resolve(self, field, value): + """Execute processor of the specific field with the value""" + if field in self._fields: + processor = self._fields[field] + return processor.build_query(value) diff --git a/graphene_django/elasticsearch/filter/processors.py b/graphene_django/elasticsearch/filter/processors.py index 7180f15..8a6e8e3 100644 --- a/graphene_django/elasticsearch/filter/processors.py +++ b/graphene_django/elasticsearch/filter/processors.py @@ -33,24 +33,15 @@ class Processor(object): """Define the argument for graphene field""" return self.filter_es.argument - def generate_es_query(self, data): + def to_attach(self, observer): """ - Define the argument for graphene field - :param data: Data passed to field in the query + Add this processor to FieldResolverObservable + :param observer: observer to attach the processors. """ - if self.variant_name in data: - value = data.get(self.variant_name) - self_query = self._build_query(value) - else: - self_query = Q("bool") + observer.attach(self.variant_name, self) if self.parent_processor is not None: - parent_query = self.parent_processor.generate_es_query(data) - parent_query += self_query - return parent_query - - else: - return self_query + self.parent_processor.to_attach(observer) def _build_field(self): """ @@ -74,7 +65,7 @@ class Processor(object): return variant_name - def _build_query(self, value): + def build_query(self, value): """ Make a query based on specific processor query :param value: Value passed to this processor