def _modify_params_for_relationships(self, entity, params, delete_first=True): entity = resolve_entity(entity) mapper = class_mapper(entity) relations = self.get_relations(entity) for relation in relations: if relation in params: prop = mapper.get_property(relation) target = prop.argument target = resolve_entity(target) value = params[relation] if value: if prop.uselist and isinstance(value, list): target_obj = [] for v in value: try: object_mapper(v) target_obj.append(v) except UnmappedInstanceError: if hasattr(target, 'primary_key'): pk = target.primary_key else: pk = class_mapper(target).primary_key if isinstance(v, string_type) and "/" in v: v = map(self._adapt_type, v.split("/"), pk) v = tuple(v) else: v = self._adapt_type(v, pk[0]) #only add those items that come back new_v = self.session.query(target).get(v) if new_v is not None: target_obj.append(new_v) elif prop.uselist: try: object_mapper(value) target_obj = [value] except UnmappedInstanceError: mapper = target if not isinstance(target, Mapper): mapper = class_mapper(target) if isinstance(mapper.primary_key[0].type, Integer): value = int(value) target_obj = [self.session.query(target).get(value)] else: try: object_mapper(value) target_obj = value except UnmappedInstanceError: if isinstance(value, string_type) and "/" in value: value = map(self._adapt_type, value.split("/"), prop.remote_side) value = tuple(value) else: value = self._adapt_type(value, list(prop.remote_side)[0]) target_obj = self.session.query(target).get(value) params[relation] = target_obj else: del params[relation] return params
def _get_related_class(self, entity, relation): entity = resolve_entity(entity) mapper = class_mapper(entity) prop = mapper.get_property(relation) target = resolve_entity(prop.argument) if not hasattr(target, 'class_'): target = class_mapper(target) return target.class_
def _modify_params_for_dates(self, entity, params): entity = resolve_entity(entity) mapper = class_mapper(entity) for key, value in list(params.items()): if key in mapper.c and value is not None: field = mapper.c[key] if hasattr(field, 'type'): if isinstance(field.type, DateTime): if not isinstance(value, datetime): dt = datetime.strptime(value[:19], '%Y-%m-%d %H:%M:%S') params[key] = dt elif isinstance(field.type, Date): if not isinstance(value, date): dt = datetime.strptime(value, '%Y-%m-%d').date() params[key] = dt elif isinstance(field.type, Interval): if not isinstance(value, timedelta): d = re.match( r'((?P<days>\d+) days, )?(?P<hours>\d+):' r'(?P<minutes>\d+):(?P<seconds>\d+)', str(value)).groupdict(0) dt = timedelta(**dict(( (key, int(value)) for key, value in list(d.items()) ))) params[key] = dt return params
def get_dropdown_options(self, entity, field_name, view_names=None): if view_names is None: view_names = ['_name', 'name', 'description', 'title'] if self.session is None: warn('No dropdown options will be shown for %s. ' 'Try passing the session into the initialization ' 'of your form base object so that this sprocket ' 'can have values in the drop downs'%entity) return [] field = self.get_field(entity, field_name) target_field = entity if isinstance(field, PropertyLoader): target_field = field.argument target_field = resolve_entity(target_field) #some kind of relation if isinstance(target_field, Mapper): target_field = target_field.class_ pk_fields = self.get_primary_fields(target_field) view_name = self.get_view_field_name(target_field, view_names) rows = self.session.query(target_field).all() if len(pk_fields) == 1: def build_pk(row): return getattr(row, pk_fields[0]) else: def build_pk(row): return "/".join([str(getattr(row, pk)) for pk in pk_fields]) return [ (build_pk(row), getattr(row, view_name)) for row in rows ]
def is_unique(self, entity, field_name, value): entity = resolve_entity(entity) field = getattr(entity, field_name) try: self.session.query(entity).filter(field==value).one() except NoResultFound: return True return False
def get_field(self, entity, name): entity = resolve_entity(entity) mapper = class_mapper(entity) try: return getattr(mapper.c, name) except (InvalidRequestError, AttributeError): try: return mapper.get_property(name) except InvalidRequestError: raise AttributeError
def is_relation(self, entity, field_name): entity = resolve_entity(entity) mapper = class_mapper(entity) try: property = mapper.get_property(field_name) except InvalidRequestError: return False if isinstance(property, PropertyLoader): return True
def get_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) field_names = list(mapper.c.keys()) for prop in mapper.iterate_properties: try: mapper.c[prop.key] field_names.append(prop.key) except KeyError: mapper.get_property(prop.key) field_names.append(prop.key) return field_names
def get_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) field_names = list(mapper.c.keys()) for prop in mapper.iterate_properties: try: getattr(mapper.c, prop.key) field_names.append(prop.key) except AttributeError: mapper.get_property(prop.key) field_names.append(prop.key) return field_names
def get_primary_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) fields = [] for field_name in self.get_fields(entity): try: value = mapper.c[field_name] except KeyError: # Relations won't be attributes, but can't be primary anyway. continue if value.primary_key and not field_name in fields: fields.append(field_name) return fields
def get_primary_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) fields = [] for field_name in self.get_fields(entity): try: value = getattr(mapper.c, field_name) except AttributeError: # Relations won't be attributes, but can't be primary anyway. continue if value.primary_key and not field_name in fields: fields.append(field_name) return fields
def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, field_names=[], filters={}, substring_filters=[], **kw): entity = resolve_entity(entity) query = self.session.query(entity) filters = self._modify_params_for_dates(entity, filters) filters = self._modify_params_for_relationships(entity, filters) for field_name, value in filters.items(): field = getattr(entity, field_name) if self.is_relation(entity, field_name) and isinstance(value, list): value = value[0] query = query.filter(field.contains(value)) elif field_name in substring_filters and self.is_string(entity, field_name): escaped_value = re.sub('[\\\\%\\[\\]_]', '\\\\\g<0>', value.lower()) query = query.filter(func.lower(field).contains(escaped_value, escape='\\')) else: query = query.filter(field==value) count = query.count() if order_by is not None: if self.is_relation(entity, order_by): mapper = class_mapper(entity) class_ = None for prop in mapper.iterate_properties: try: class_ = prop.mapper.class_ except (AttributeError, KeyError): pass query = self.session.query(entity).join(order_by) f = self.get_view_field_name(class_, field_names) field = self.get_field(class_, f) else: field = self.get_field(entity, order_by) if desc: field = _desc(field) query = query.order_by(field) if offset is not None: query = query.offset(offset) if limit is not None: query = query.limit(limit) objs = query.all() return count, objs
def create(self, entity, params): entity = resolve_entity(entity) params = self._modify_params_for_dates(entity, params) params = self._modify_params_for_relationships(entity, params) obj = entity() relations = self.get_relations(entity) mapper = class_mapper(entity) for key, value in params.items(): if value is not None: if isinstance(value, FieldStorage): value = value.file.read() try: if key not in relations and value and isinstance(mapper.columns[key].type, Integer): value = int(value) except KeyError: pass setattr(obj, key, value) self.session.add(obj) self.session.flush() return obj
def get_dropdown_options(self, entity, field_name, view_names=None): if view_names is None: view_names = self.default_view_names if self.session is None: warn('No dropdown options will be shown for %s. ' 'Try passing the session into the initialization ' 'of your form base object so that this sprocket ' 'can have values in the drop downs' % entity) return [] field = self.get_field(entity, field_name) target_field = entity if isinstance(field, PropertyLoader): target_field = field.argument target_field = resolve_entity(target_field) #some kind of relation if isinstance(target_field, Mapper): target_field = target_field.class_ pk_fields = self.get_primary_fields(target_field) view_name = self.get_view_field_name(target_field, view_names) rows = self.session.query(target_field).all() if len(pk_fields) == 1: def build_pk(row): return getattr(row, pk_fields[0]) else: def build_pk(row): return "/".join([str(getattr(row, pk)) for pk in pk_fields]) return [(build_pk(row), getattr(row, view_name)) for row in rows]
def create(self, entity, params): entity = resolve_entity(entity) params = self._modify_params_for_dates(entity, params) params = self._modify_params_for_relationships(entity, params) obj = entity() relations = self.get_relations(entity) mapper = class_mapper(entity) for key, value in params.items(): if value is not None: if isinstance(value, FieldStorage): value = value.file.read() try: if key not in relations and value and isinstance( mapper.columns[key].type, Integer): value = int(value) except KeyError: pass setattr(obj, key, value) self.session.add(obj) self.session.flush() return obj
def _find_title_column(self, entity): entity = resolve_entity(entity) for column in class_mapper(entity).columns: if 'title' in column.info and column.info['title']: return column.key return None
def get_synonyms(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) return [prop.key for prop in mapper.iterate_properties if isinstance(prop, SynonymProperty)]
def _relates_many(self, entity, field_name): entity = resolve_entity(entity) mapper = class_mapper(entity) property = mapper.get_property(field_name) return property.uselist
def _modify_params_for_relationships(self, entity, params): entity = resolve_entity(entity) mapper = class_mapper(entity) relations = self.get_relations(entity) for relation in relations: if relation in params: prop = mapper.get_property(relation) target = prop.argument target = resolve_entity(target) value = params[relation] if value: if prop.uselist and isinstance(value, list): target_obj = [] for v in value: try: object_mapper(v) target_obj.append(v) except UnmappedInstanceError: if hasattr(target, 'primary_key'): pk = target.primary_key else: pk = class_mapper(target).primary_key if isinstance(v, string_type) and "/" in v: v = map(self._adapt_type, v.split("/"), pk) v = tuple(v) else: v = self._adapt_type(v, pk[0]) #only add those items that come back new_v = self.session.query(target).get(v) if new_v is not None: target_obj.append(new_v) elif prop.uselist: try: object_mapper(value) target_obj = [value] except UnmappedInstanceError: mapper = target if not isinstance(target, Mapper): mapper = class_mapper(target) value = self._adapt_type(value, mapper.primary_key[0]) target_obj = [ self.session.query(target).get(value) ] else: try: object_mapper(value) target_obj = value except UnmappedInstanceError: if isinstance(value, string_type) and "/" in value: value = map(self._adapt_type, value.split("/"), prop.remote_side) value = tuple(value) else: value = self._adapt_type( value, list(prop.remote_side)[0]) target_obj = self.session.query(target).get(value) params[relation] = target_obj else: if prop.uselist: params[relation] = [] else: params[relation] = None return params
def get_relations(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) return [prop.key for prop in mapper.iterate_properties if isinstance(prop, PropertyLoader)]
def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, filters={}, substring_filters=[], search_related=False, related_field_names=None, **kw): entity = resolve_entity(entity) query = self.session.query(entity) filters = self._modify_params_for_dates(entity, filters) if search_related: # Values for related fields contain the text to search filters = self._modify_params_for_related_searches( entity, filters, view_names=related_field_names, substrings=substring_filters) else: # Values for related fields contain the primary key filters = self._modify_params_for_relationships(entity, filters) for field_name, value in filters.items(): field = getattr(entity, field_name) if self.is_relation(entity, field_name) and isinstance( value, list): related_class = self._get_related_class(entity, field_name) related_pk = self.get_primary_field(related_class) related_pk_col = getattr(related_class, related_pk) related_pk_values = (getattr(v, related_pk) for v in value) if self._relates_many(entity, field_name): field_filter = field.any( related_pk_col.in_(related_pk_values)) else: field_filter = field.has( related_pk_col.in_(related_pk_values)) query = query.filter(field_filter) elif field_name in substring_filters and self.is_string( entity, field_name): escaped_value = self._escape_like(value.lower()) query = query.filter( func.lower(field).contains(escaped_value, escape='*')) else: query = query.filter(field == value) count = query.count() if order_by is not None: if not isinstance(order_by, (tuple, list)): order_by = [order_by] if not isinstance(desc, (tuple, list)): desc = [desc] for sort_by, sort_descending in zip_longest(order_by, desc): if self.is_relation(entity, sort_by): mapper = class_mapper(entity) class_ = self._get_related_class(entity, sort_by) query = query.outerjoin(sort_by) f = self.get_view_field_name(class_, related_field_names) field = self.get_field(class_, f) else: field = self.get_field(entity, sort_by) if sort_descending: field = _desc(field) query = query.order_by(field) if offset is not None: query = query.offset(offset) if limit is not None: query = query.limit(limit) objs = query.all() return count, objs
def _get_obj(self, entity, pkdict): entity = resolve_entity(entity) pk_names = self.get_primary_fields(entity) pks = tuple([pkdict[n] for n in pk_names]) return self.session.query(entity).get(pks)
def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, filters={}, substring_filters=[], search_related=False, related_field_names=None, **kw): entity = resolve_entity(entity) query = self.session.query(entity) filters = self._modify_params_for_dates(entity, filters) if search_related: # Values for related fields contain the text to search filters = self._modify_params_for_related_searches(entity, filters, view_names=related_field_names, substrings=substring_filters) else: # Values for related fields contain the primary key filters = self._modify_params_for_relationships(entity, filters) for field_name, value in filters.items(): field = getattr(entity, field_name) if self.is_relation(entity, field_name) and isinstance(value, list): related_class = self._get_related_class(entity, field_name) related_pk = self.get_primary_field(related_class) related_pk_col = getattr(related_class, related_pk) related_pk_values = (getattr(v, related_pk) for v in value) if self._relates_many(entity, field_name): field_filter = field.any(related_pk_col.in_(related_pk_values)) else: field_filter = field.has(related_pk_col.in_(related_pk_values)) query = query.filter(field_filter) elif field_name in substring_filters and self.is_string(entity, field_name): escaped_value = self._escape_like(value.lower()) query = query.filter(func.lower(field).contains(escaped_value, escape='*')) else: query = query.filter(field==value) count = query.count() if order_by is not None: if not isinstance(order_by, (tuple, list)): order_by = [order_by] if not isinstance(desc, (tuple, list)): desc = [desc] for sort_by, sort_descending in zip_longest(order_by, desc): if self.is_relation(entity, sort_by): mapper = class_mapper(entity) class_ = self._get_related_class(entity, sort_by) query = query.outerjoin(sort_by) f = self.get_view_field_name(class_, related_field_names) field = self.get_field(class_, f) else: field = self.get_field(entity, sort_by) if sort_descending: field = _desc(field) query = query.order_by(field) if offset is not None: query = query.offset(offset) if limit is not None: query = query.limit(limit) objs = query.all() return count, objs
def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, field_names=[], filters={}, substring_filters=[], **kw): entity = resolve_entity(entity) query = self.session.query(entity) filters = self._modify_params_for_dates(entity, filters) filters = self._modify_params_for_relationships(entity, filters) for field_name, value in filters.items(): field = getattr(entity, field_name) if self.is_relation(entity, field_name) and isinstance( value, list): value = value[0] query = query.filter(field.contains(value)) elif field_name in substring_filters and self.is_string( entity, field_name): escaped_value = re.sub('[\\\\%\\[\\]_]', '\\\\\g<0>', value.lower()) query = query.filter( func.lower(field).contains(escaped_value, escape='\\')) else: query = query.filter(field == value) count = query.count() if order_by is not None: if self.is_relation(entity, order_by): mapper = class_mapper(entity) class_ = None for prop in mapper.iterate_properties: try: class_ = prop.mapper.class_ except (AttributeError, KeyError): pass query = self.session.query(entity).join(order_by) f = self.get_view_field_name(class_, field_names) field = self.get_field(class_, f) else: field = self.get_field(entity, order_by) if desc: field = _desc(field) query = query.order_by(field) if offset is not None: query = query.offset(offset) if limit is not None: query = query.limit(limit) objs = query.all() return count, objs