def find(self, rtype, key, val): """ Given a resource type & a single key/val find the model A single instantiated model object found by the key/val will be returned if a match is found in the database. If no record can be found then return None. WARN: This isn't for complex queries! Use search() instead. :return: model or None """ model = rtype_to_model(rtype) param = {'key': key, 'val': val} query = """ SELECT {cols} FROM {table} WHERE {key} = %(val)s; """ query = query.format( cols=self.field_cols(model), key=key, table=rtype, ) signals.pre_find.send(model.__class__, model=model) result = self.query(query, param=param) if result: result = model(result[0]) signals.post_find.send(model.__class__, model=result) return result or None
def _validate_param(rtype, fields): """ Ensure the sparse fields exists on the models """ try: # raises ValueError if not found model = rtype_to_model(rtype) model_fields = model.all_fields except ValueError: raise InvalidQueryParams(**{ 'detail': 'The fields query param provided with a ' 'field type of "%s" is unknown.' % rtype, 'links': LINK, 'parameter': PARAM, }) for field in fields: if field not in model_fields: raise InvalidQueryParams(**{ 'detail': 'The fields query param "TYPE" of "%s" ' 'is not possible. It does not have a field ' 'by the name of "%s".' % (rtype, field), 'links': LINK, 'parameter': PARAM, })
def search(self, rtype, **kwargs): """ Search for the model by assorted criteria Quite a bit needs to happen for a search processing! The breakdown is we need to apply the query parameters where applicable. These include pagination, sorting, & filtering. Additionally, models can declare there own static filters or static query that should be applied. For static filters a model can opt-in with a `search_filters` property & for a static query to append a `search_query` property must be present. """ model = rtype_to_model(rtype) param = {} pages = self.pages_query(kwargs.get('pages')) sorts = self.sorts_query(kwargs.get( 'sorts', [Sortable(goldman.config.SORT)] )) query = """ SELECT {cols}, count(*) OVER() as _count FROM {table} """ query = query.format( cols=self.field_cols(model), table=rtype, ) filters = kwargs.get('filters', []) filters += getattr(model, 'search_filters', []) or [] if filters: where, param = self.filters_query(filters) query += where model_query = getattr(model, 'search_query', '') or '' if filters and model_query: model_query = ' AND ' + model_query elif model_query: model_query = ' WHERE ' + model_query query += model_query query += sorts query += pages signals.pre_search.send(model.__class__, model=model) result = self.query(query, param=param) models = [model(res) for res in result] if models: signals.post_search.send(model.__class__, models=result) pages = kwargs.get('pages') if pages and result: pages.total = result[0]['_count'] return models