def build_filters(self, filters=None, request=None): basedn = None filter = None parts = [] for arg_name, arg_value in filters.items(): if arg_name in ['limit', 'offset']: # XXX permit limit arg continue if arg_name not in self.fields or arg_name in ['limit']: raise InvalidFilterError( "Not a valid filter: {0}".format(arg_name)) if getattr(self.fields[arg_name], 'is_related', False): method = getattr(self, 'filter_on_{0}'.format(arg_name), None) if method: basedn = method(arg_value) continue else: raise InvalidFilterError( "Cannot filter on a relation field: {0}".format( arg_name)) model_field_name = self.get_model_field_name(arg_name) part = eq(model_field_name, arg_value) parts.append(part) if parts: filter = opand(*parts) search_params = SearchParams(basedn=basedn, filter=filter) return search_params
def poly_from_bbox(bbox_val): points = bbox_val.split(',') if len(points) != 4: raise InvalidFilterError("bbox must be in format 'left,bottom,right,top'") try: return Polygon.from_bbox( [float(p) for p in points]) except ValueError: raise InvalidFilterError("bbox values must be floating point")
def check_filtering(self, field_name, filter_type='exact', filter_bits=None): """ Given a field name, a optional filter type and an optional list of additional relations, determine if a field can be filtered on. If a filter does not meet the needed conditions, it should raise an ``InvalidFilterError``. If the filter meets the conditions, a list of attribute names (not field names) will be returned. """ if filter_bits is None: filter_bits = [] if not field_name in self._meta.filtering: raise InvalidFilterError( "The '%s' field does not allow filtering." % field_name) # Check to see if it's an allowed lookup type. if not self._meta.filtering[field_name] in (ALL, ALL_WITH_RELATIONS): # Must be an explicit whitelist. if not filter_type in self._meta.filtering[field_name]: raise InvalidFilterError( "'%s' is not an allowed filter on the '%s' field." % (filter_type, field_name)) if self.fields[field_name].attribute is None: raise InvalidFilterError( "The '%s' field has no 'attribute' for searching with." % field_name) # Check to see if it's a relational lookup and if that's allowed. if len(filter_bits): if not getattr(self.fields[field_name], 'is_related', False): raise InvalidFilterError( "The '%s' field does not support relations." % field_name) if not self._meta.filtering[field_name] == ALL_WITH_RELATIONS: raise InvalidFilterError( "Lookups are not allowed more than one level deep on the '%s' field." % field_name) # Recursively descend through the remaining lookups in the filter, # if any. We should ensure that all along the way, we're allowed # to filter on that field by the related resource. related_resource = self.fields[field_name].get_related_resource( None) return [self.fields[field_name].attribute ] + related_resource.check_filtering( filter_bits[0], filter_type, filter_bits[1:]) return [self.fields[field_name].attribute]
def check_filtering(self, field_name, filter_type='contains'): if not field_name in self._meta.filtering: raise InvalidFilterError( "The '%s' field does not allow filtering." % field_name) if not filter_type in self._meta.filtering[field_name]: raise InvalidFilterError( "'%s' is not an allowed filter on the '%s' field." % (filter_type, field_name)) return True
def srid_to_srs(srid): if not srid: srid = DEFAULT_SRID try: srid = int(srid) except ValueError: raise InvalidFilterError("'srid' must be an integer") try: srs = SpatialReference(srid) except SRSException: raise InvalidFilterError("SRID %d not found (try 4326 for GPS coordinate system)" % srid) return srs
def build_filters(self, filters=None): if filters is None: raise InvalidFilterError("Filter fields are necessaries.") if 'session' not in filters: raise InvalidFilterError("Session field is necessary.") if 'number' not in filters: raise InvalidFilterError("Number field is necessary.") orm_filters = super(VoteResource, self).build_filters(filters) return orm_filters
def get_query_terms(self, field_name): """ Helper to determine supported filter operations for a field """ if field_name not in self.fields: raise InvalidFilterError("The '%s' field is not a valid field" % field_name) try: django_field_name = self.fields[field_name].attribute django_field = self._meta.object_class._meta.get_field(django_field_name) if hasattr(django_field, "field"): django_field = django_field.field # related field except FieldDoesNotExist: raise InvalidFilterError("The '%s' field is not a valid field name" % field_name) return django_field.get_lookups().keys()
def check_filtering(self, field_name, filter_type="exact", filter_bits=None): """ Overrides BaseModelResource.check_filtering to work with self.build_filters above """ if filter_bits is None: filter_bits = [] if field_name not in self._meta.filtering: raise InvalidFilterError("The '%s' field does not allow filtering." % field_name) # Check to see if it's an allowed lookup type. if filter_type != "exact" and self._meta.filtering[field_name] not in (ALL, ALL_WITH_RELATIONS): # Must be an explicit whitelist. if filter_type not in self._meta.filtering[field_name]: raise InvalidFilterError("'%s' is not an allowed filter on the '%s' field." % (filter_type, field_name)) if self.fields[field_name].attribute is None: raise InvalidFilterError("The '%s' field has no 'attribute' for searching with." % field_name) if len(filter_bits) == 0: # Only a field provided, match with provided filter type return [self.fields[field_name].attribute] + [filter_type] elif len(filter_bits) == 1 and filter_bits[0] in self.get_query_terms(field_name): # Match with valid filter type (i.e. contains, startswith, Etc.) return [self.fields[field_name].attribute] + filter_bits else: # Check to see if it's a relational lookup and if that's allowed. if not getattr(self.fields[field_name], "is_related", False): raise InvalidFilterError("The '%s' field does not support relations." % field_name) if not self._meta.filtering[field_name] == ALL_WITH_RELATIONS: raise InvalidFilterError( "Lookups are not allowed more than one level deep on the '%s' field." % field_name ) # Recursively descend through the remaining lookups in the filter, # if any. We should ensure that all along the way, we're allowed # to filter on that field by the related resource. related_resource = self.fields[field_name].get_related_resource(None) next_field_name = filter_bits[0] next_filter_bits = filter_bits[1:] next_filter_type = related_resource.resolve_filter_type(next_field_name, next_filter_bits, filter_type) return [self.fields[field_name].attribute] + related_resource.check_filtering( next_field_name, next_filter_type, next_filter_bits )
def dispatch(self, request_type, request, **kwargs): """ Override of the default dispatch method for a resource. This provides front end level caching for TastyPie APIs. This requires fairly high level tinkering with some API basics but provides very effective caching. """ # Since we are hitting this before other validation # Ensure that a format has been passed in. if getattr(settings, 'API_CACHE_ENABLE', False): response_format = request.GET.get('format', None) if response_format is None: if settings.TASTYPIE_DEFAULT_FORMATS: response_format = settings.TASTYPIE_DEFAULT_FORMATS[0] else: raise InvalidFilterError(u'Format is required.') data = self.get_cache(request, force_jsonp=self.is_jsonp(request)) if data: if self.is_jsonp(request): data = self.wrap_json_response(request, data) # If the request is a valid cache format, return it. return_string = data content_type = self._get_valid_content_type(response_format) return HttpResponse(return_string, content_type=content_type, status=200) else: # If no cache is found go 'Move Along'... return super(CachedResource, self).dispatch(request_type, request, **kwargs) else: return super(CachedResource, self).dispatch(request_type, request, **kwargs)
def apply_filters(self, request, filters): """ An ORM-specific implementation of ``apply_filters``. Emulates native tastypie django-specific filters. """ qs_filters = [] qs_set_filters = {} for filter_expr, value in filters.items(): filter_bits = filter_expr.split(LOOKUP_SEP) field_name = filter_bits.pop(0) filter_type = 'exact' if not field_name in self.fields: # It's not a field we know about. Move along citizen. continue # resolve filter type if len(filter_bits) and filter_bits[-1] in QUERY_TERMS: filter_type = filter_bits.pop() lookup_bits = self.check_filtering(field_name, filter_type, filter_bits) # check, whether the specified atribute is a single value or set; # also get final attribute type # (Pony ORM-specific) is_set = False t = self._meta.object_class for bit in lookup_bits: a = getattr(t,bit,None) if not a: raise InvalidFilterError("The attribute %s not found for %s" % (bit,t)) t = a.py_type if issubclass(t,orm.core.Entity) and isinstance(a,orm.Set): is_set = True # split single and set-oriented filters to emulate django filters if not is_set: flt = self.combine_lookup_and_value(t,filter_type,lookup_bits,value,'o.') if flt: qs_filters.append(flt) else: set_object = tuple(lookup_bits[:-1]) flt = self.combine_lookup_and_value(t,filter_type,lookup_bits[-1:],value,'p.') if flt: if not set_object in qs_set_filters: qs_set_filters[set_object] = [] qs_set_filters[set_object].append(flt) q = self.get_object_list(request) for f in qs_filters: q.filter(f) for set_object in qs_set_filters: q.filter("orm.exists(p for p in %s if %s)" % ( 'o.'+'.'.join(set_object), ' and '.join([('(%s)' % flt) for flt in qs_set_filters[set_object]]) )) return q
def build_filters(self, filters={}): orm_filters = super(ModelResource, self).build_filters(filters) if ('Q' in filters): if (not 'Q' in self._meta.filtering or self._meta.filtering['Q'] is not ALL): raise InvalidFilterError( 'Q filtering is not allowed for this resource.') q = re.sub('from|import|del|sleep|while|for', '', filters['Q']) try: orm_filters.update({'Q': (eval(q))}) except: raise InvalidFilterError('Q has wrong syntax') return orm_filters
def _date_consumer(key, value): if '.' in key and key.split(".")[0] == field: prefix, qualifier = key.split(".", maxsplit=1) try: return date_filter(qualifier, value) except ValueError as e: raise InvalidFilterError(str(e)) return {}
def build_filters(self, filters=None): res = super(AlbumResource, self).build_filters(filters) if 'year' in filters: try: res.update({'year': int(filters['year'])}) except: raise InvalidFilterError('year must be an integer!') return res
def build_filters(self, filters=None): res = super(ReviewResource, self).build_filters(filters) if 'tid' in filters: try: res.update({'tid': str(filters['tid'])}) except: raise InvalidFilterError('tid must be an integer!') return res
def apply_filters(self, request, applicable_filters): semi_filtered = self.get_object_list(request) if applicable_filters: try: if hasattr(applicable_filters, 'keys'): semi_filtered = semi_filtered.filter(**applicable_filters) else: semi_filtered = semi_filtered.filter(applicable_filters) except Exception, ex: raise InvalidFilterError('%s' % ex)
def apply_sorting(self, objects, options=None): if options and 'lon' in options and 'lat' in options: try: lat = float(options['lat']) lon = float(options['lon']) except ValueError: raise InvalidFilterError("'lon' and 'lat' need to be floats") pnt = Point(lon, lat, srid=4326) pnt.transform(PROJECTION_SRID) objects = objects.distance(pnt).order_by('distance') return super(POIResource, self).apply_sorting(objects, options)
def check_filtering(self, field_name, filter_type='exact', filter_bits=None): if filter_bits is None: filter_bits = [] if field_name not in self._meta.filtering: raise InvalidFilterError("The '%s' field does not allow filtering." % field_name) # Check to see if it's an allowed lookup type. if self._meta.filtering[field_name] not in QUERY_TERMS: # Must be an explicit whitelist. if filter_type not in self._meta.filtering[field_name]: raise InvalidFilterError( "'%s' is not an allowed filter on the '%s' field." % ( filter_type, field_name )) if self.fields[field_name].attribute is None: raise InvalidFilterError( "The '%s' field has no 'attribute' for searching with." % field_name ) return [self.fields[field_name].attribute]
def build_filters(self, filters=None, **kwargs): orm_filters = super(TemplateSchemeResource, self).build_filters(filters, **kwargs) if "project__id" in filters and "template_id" in filters: template_id = filters.pop("template_id")[0] project_id = filters.pop("project__id")[0] try: template = TaskTemplate.objects.get(pk=template_id, project_id=project_id) except TaskTemplate.DoesNotExist: message = "flow template[id={template_id}] in project[id={project_id}] does not exist".format( template_id=template_id, project_id=project_id ) logger.error(message) raise InvalidFilterError(message) except Exception as e: message = "Error on getting template[id={template_id}] in project[id={project_id}]: {error}".format( template_id=template_id, project_id=project_id, error=e ) logger.error(message) raise InvalidFilterError(message) orm_filters.update({"template__template_id": template.pipeline_template.template_id}) elif "pk" not in filters: # 不允许请求全部执行方案 orm_filters.update({"unique_id": ""}) return orm_filters
def combine_lookup_and_value(self,final_type,filter_type,lookup_bits,value,prefix): attribute = prefix + '.'.join(lookup_bits) value_convertor = QUERY_TERM_CONVERT_VALUE[final_type] if filter_type == 'isnull': value_convertor = QUERY_TERM_CONVERT_VALUE[bool] elif filter_type in ('day','month','year'): value_convertor = QUERY_TERM_CONVERT_VALUE[int] try: if filter_type in ('in','range'): value = [repr(value_convertor(v)) for v in value.split(',')] else: value = repr(value_convertor(value)) except: raise InvalidFilterError("Value %s is not allowed for '%s' filter with attribute '%s'" % (repr(value),filter_type,'.'.join(lookup_bits))) expr = QUERY_TERMS[filter_type] return expr(attribute,value)
def build_filters(self, filters=None): if filters is None: filters = {} orm_filters = super(PostResource, self).build_filters(filters) if "member_id" in filters: try: member = Member.objects.get(pk=filters['member_id']) except Member.DoesNotExist: raise InvalidFilterError("Could not find member id %s" % filters['member_id']) links = Link.objects.for_model(member) feeds = Feed.objects.filter(url__in=map(lambda x: x.url, links), is_active=True) orm_filters["feed__in"] = feeds return orm_filters
def build_filters(self, filters=None): # Override the filters so we can stop Tastypie silently ignoring # invalid filters. That will cause an invalid filtering just to return # lots of results. if filters is None: filters = {} qs_filters = {} for filter_expr, value in filters.items(): filter_bits = filter_expr.split(LOOKUP_SEP) field_name = filter_bits.pop(0) filter_type = 'exact' if not field_name in self.fields: # Don't just ignore this. Tell the world. Shame I have to # override all this, just to do this. raise InvalidFilterError('Not a valid filtering field: %s' % field_name) if len(filter_bits) and filter_bits[-1] in QUERY_TERMS: filter_type = filter_bits.pop() lookup_bits = self.check_filtering(field_name, filter_type, filter_bits) if value in ['true', 'True', True]: value = True elif value in ['false', 'False', False]: value = False elif value in ('nil', 'none', 'None', None): value = None # Split on ',' if not empty string and either an in or range # filter. if filter_type in ('in', 'range') and len(value): if hasattr(filters, 'getlist'): value = filters.getlist(filter_expr) else: value = value.split(',') db_field_name = LOOKUP_SEP.join(lookup_bits) qs_filter = '%s%s%s' % (db_field_name, LOOKUP_SEP, filter_type) qs_filters[qs_filter] = value return dict_strip_unicode_keys(qs_filters)
def build_filters(self, filters=None, ignore_bad_filters=True): """ Example: {"or":[{"and":[{"not":{"status":"S"}},{"performer":null}]},{"status":"P"}]} Result: (OR: (AND: (NOT (AND: (u'status', u'S'))), (u'performer__isnull', True)), (u'status', u'P')) """ if filters is None: filters = {} orm_filters = {} qset = {} if ('filter' in filters): query = filters['filter'] try: qset = self.parse_filter_condition(json.loads(query)) except Exception, ex: raise InvalidFilterError("%s" % ex)
def obj_get_list(self, bundle, **kwargs): result = super(PersonResource, self).obj_get_list(bundle, **kwargs) filters = bundle.request.GET.copy() if 'has_contacts' in filters: # Count the number of contacts the person has filters['has_contacts'] = filters['has_contacts'].lower() if filters['has_contacts'] == 'true': result = result.has_contacts() elif filters['has_contacts'] == 'false': result = result.doesnt_have_contacts() else: raise InvalidFilterError( "'has_contacts' field must either be 'true' or 'false'.") if 'instance_id' in filters: result = result.filter( writeit_instances__id=filters['instance_id']) return result
def check_filtering(self, field_name, filter_type='exact', filter_bits=None): """Verify that filter_bits does not begin with a related field lookup. This allows the user to make filters that begin with a related lookup, but not filters that involve multiple related lookups ("second-order" lookups). """ # We want to call the super method right before we return, so wrap it # in a lambda expression -- that way we know it's always called right result = lambda: (super(FirstOrderResource, self). check_filtering(field_name, filter_type, filter_bits)) if filter_bits and field_name in self.fields: # NB: filter_bits must be non-empty in addition to not being None # get the field object target_field = self.fields[field_name] # Figure out if it's a relationship field try: is_related = target_field.is_related except AttributeError: is_related = False if not is_related: # It isn't, so we don't have to do anything return result() # get the resource at the "other end" of this relationship target_resource = target_field.get_related_resource(None) # get the next part of the filter next_filter = filter_bits[0] if next_filter not in target_resource.fields: # the filter doesn't refer to a field on the resource return result() next_field = target_resource.fields[next_filter] try: is_second_order = next_field.is_related except AttributeError: is_second_order = False if is_second_order: # The filter refers to a relationship field on the resource, # so we need to abort since we can't handle those correctly raise InvalidFilterError("Second-order relationship traversal"+ " is not allowed.") return result()
def build_filters(self, filters=None, **kwargs): orm_filters = super(TemplateSchemeResource, self).build_filters(filters, **kwargs) if 'project__id' in filters and 'template_id' in filters: template_id = filters.pop('template_id')[0] project_id = filters.pop('project__id')[0] try: template = TaskTemplate.objects.get(pk=template_id, project_id=project_id) except TaskTemplate.DoesNotExist: message = 'flow template[id={template_id}] in project[id={project_id}] does not exist'.format( template_id=template_id, project_id=project_id) logger.error(message) raise InvalidFilterError(message) orm_filters.update({ 'template__template_id': template.pipeline_template.template_id }) elif 'pk' not in filters: # 不允许请求全部执行方案 orm_filters.update({'unique_id': ''}) return orm_filters
def build_filters(self, filters=None, ignore_bad_filters=False): subjects = None ids = None user = None if filters is None: filters = {} if 'subjects' in filters: subjects = filters['subjects'] del filters['subjects'] if 'ids' in filters: ids = filters['ids'] del filters['ids'] if 'user' in filters: user = filters['user'] del filters['user'] orm_filters = super(ImageResource, self).build_filters(filters, ignore_bad_filters) if subjects: from astrobin_apps_platesolving.models import Solution def fix_catalog(name): capitalize = ( 'ngc', 'm', 'b', 'ic', 'ugc', 'pgc', ) if name.lower() in [x.lower() for x in capitalize]: return name.upper() + ' ' remove = ('name', ) if name.lower() in [x.lower() for x in remove]: return '' return name + ' ' def fix_name(name): import re fix = re.compile('^(?P<catalog>M|NGC)(?P<name>\d+)', re.IGNORECASE) m = fix.match(name) if m: return '%s%s' % (fix_catalog( m.group('catalog')), m.group('name')) return name qs = Solution.objects.filter( objects_in_field__icontains=fix_name(subjects))[:100] orm_filters['pk__in'] = [i.object_id for i in qs] if ids: max = 100 if len(ids) > max: raise InvalidFilterError( f'Please do not request over {max} image IDs') orm_filters['pk__in'] = ids.split(',') if user: orm_filters['user__username'] = user return orm_filters