def select_related(self, *args): select_related = {'action': 'db__select_related', 'fields': []} for arg in args: # fr the time been we overlook the after the '__' if '__' in arg: arg = arg.split('__')[0] if not hasattr(self.model, arg): raise QuerysetError('{} is not a {} attribute.'.format( arg, self.model.__name__)) if not isinstance(getattr(self.model, arg), ForeignKey): raise QuerysetError( '{} is not a ForeignKey Field for {}.'.format( arg, self.model.__name__)) model = self.orm.get_model(getattr(self.model, arg).foreign_key) right_table = model.table_name or model.__name__.lower() left_table = self.model.table_name or self.model.__name__.lower() fields_formatter = ', '.join([ '{right_table}.{field} AS {right_table}€$$€{field}'.format( right_table=right_table, field=field) for field in model.get_db_columns() ]) select_related['fields'].append({ 'right_table': right_table, 'left_table': left_table, 'foreign_field': arg, 'model_db_pk': model.db_pk, 'fields_formatter': fields_formatter, 'orm_fieldname': arg, }) queryset = self._copy_me() queryset.query.append(select_related) return queryset
def select_related(self, *args): select_related = {"action": "db__select_related", "fields": []} for arg in args: # fr the time been we overlook the after the '__' if "__" in arg: arg = arg.split("__")[0] if not hasattr(self.model, arg): raise QuerysetError("{} is not a {} attribute.".format( arg, self.model.__name__)) if not isinstance(getattr(self.model, arg), ForeignKey): raise QuerysetError( "{} is not a ForeignKey Field for {}.".format( arg, self.model.__name__)) model = self.orm.get_model(getattr(self.model, arg).foreign_key) right_table = model.table_name or model.__name__.lower() left_table = self.model.table_name or self.model.__name__.lower() fields_formatter = ", ".join([ "{right_table}.{field} AS {right_table}€$$€{field}".format( right_table=right_table, field=field) for field in model.get_db_columns() ]) select_related["fields"].append({ "right_table": right_table, "left_table": left_table, "foreign_field": arg, "model_db_pk": model.db_pk, "fields_formatter": fields_formatter, "orm_fieldname": arg, }) queryset = self._copy_me() queryset.query.append(select_related) return queryset
async def calculate(self, field_name, operation): if hasattr(self.model, field_name): field = getattr(self.model, field_name) else: raise QuerysetError('{} wrong field name for model {}'.format( field_name, self.model.__name__)) if not isinstance(field, NumberField): raise QuerysetError('{} is not a numeric field'.format(field_name)) query = self.query_copy() query[0]['select'] = '{}({})'.format(operation, field_name) resp = await self.db_request(query) for v in resp.values(): return v
async def __getitem__(self, key): if isinstance(key, slice): # control the keys values if key.start is not None and key.start < 0: raise QuerysetError('Negative indices are not allowed') if key.stop is not None and key.stop < 0: raise QuerysetError('Negative indices are not allowed') if key.step is not None: raise QuerysetError('Step on Queryset is not allowed') # asign forward and stop to the modelmanager and return it self.forward = key.start self.stop = key.stop if key.start is None: self.forward = 0 return self elif isinstance(key, int): # if its an int, the developer wants the object directly if key < 0: raise QuerysetError('Negative indices are not allowed') conn = await self.db_manager.get_conn() cursor = self._cursor if not cursor: query = self.db_manager.construct_query(deepcopy(self.query)) cursor = Cursor( conn, query[0], values=query[1], forward=key, ) async for res in cursor: return self.modelconstructor(res) raise IndexError('That {} index does not exist'.format( self.model.__name__)) else: raise TypeError("Invalid argument type.")
def only(self, *args): # retrieves from the database only the attrs requested # all the rest come as None for arg in args: if not hasattr(self.model, arg): raise QuerysetError('{} is not a correct field for {}'.format( arg, self.model.__name__)) queryset = self.queryset() queryset.query = self.query_copy() queryset.query[0]['select'] = ','.join(args) return queryset
def order_by(self, *args): # retrieves from the database only the attrs requested # all the rest come as None final_args = [] for arg in args: if arg[0] == '-': arg = arg[1:] final_args.append('-' + arg) else: final_args.append(arg) if not hasattr(self.model, arg): raise QuerysetError('{} is not a correct field for {}'.format( arg, self.model.__name__)) queryset = self.queryset() queryset.query = self.query_copy() queryset.query[0]['ordering'] = final_args return queryset
def calc_filters(self, kwargs, exclude): # recompose the filters bool_string = exclude and 'NOT ' or '' filters = [] for k, v in kwargs.items(): # we format the key, the conditional and the value operator = '{t_n}.{k} = {v}' lookup = None if len(k.split('__')) > 1: k, lookup = k.split('__') operator = LOOKUP_OPERATOR[lookup] field = getattr(self.model, k) string_lookups = [ 'exact', 'iexact', 'contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', ] operator_formater = { 't_n': self.model.table_name or self.model.__name__.lower(), 'k': field.db_column, 'v': v } if operator == '({t_n}.{k}>={min} AND {t_n}.{k}<={max})': if not isinstance(v, (tuple, list)): raise QuerysetError( '{} should be list or a tuple'.format(lookup)) if len(v) != 2: raise QuerysetError( 'Not a correct tuple/list definition, should be of size 2' ) operator_formater.update({ 'min': field.sanitize_data(v[0]), 'max': field.sanitize_data(v[1]), }) elif lookup in string_lookups: is_charfield = isinstance(field, CharField) # is_othercharfield = issubclass(field, CharField) # if not is_charfield or not is_othercharfield: if not is_charfield: raise QuerysetError( '{} not allowed in non CharField fields'.format( lookup)) operator_formater['v'] = field.sanitize_data(v) else: if isinstance(v, (list, tuple)): # check they are correct items and serialize v = ','.join([ "'{}'".format(field.sanitize_data(si)) if isinstance( si, str) else str(si) for si in v ]) elif v is None: v = field.sanitize_data(v)[1:-1] operator = operator.replace('=', 'IS') elif isinstance(v, datetime.datetime) or isinstance( field, (CharField)): v = "'{}'".format(v) else: v = field.sanitize_data(v) operator_formater['v'] = v filters.append(bool_string + operator.format(**operator_formater)) return filters
def calc_filters(self, kwargs, exclude): # recompose the filters bool_string = exclude and "NOT " or "" filters = [] for k, v in kwargs.items(): # we format the key, the conditional and the value operator = "{t_n}.{k} = {v}" lookup = None if len(k.split("__")) > 1: k, lookup = k.split("__") operator = LOOKUP_OPERATOR[lookup] field = getattr(self.model, k) string_lookups = [ "exact", "iexact", "contains", "icontains", "startswith", "istartswith", "endswith", "iendswith", ] operator_formater = { "t_n": self.model.table_name or self.model.__name__.lower(), "k": field.db_column, "v": v, } if operator == "({t_n}.{k}>={min} AND {t_n}.{k}<={max})": if not isinstance(v, (tuple, list)): raise QuerysetError( "{} should be list or a tuple".format(lookup)) if len(v) != 2: raise QuerysetError( "Not a correct tuple/list definition, should be of size 2" ) operator_formater.update({ "min": field.sanitize_data(v[0]), "max": field.sanitize_data(v[1]) }) elif lookup in string_lookups: is_charfield = isinstance(field, CharField) # is_othercharfield = issubclass(field, CharField) # if not is_charfield or not is_othercharfield: if not is_charfield: raise QuerysetError( "{} not allowed in non CharField fields".format( lookup)) operator_formater["v"] = field.sanitize_data(v) else: if isinstance(v, (list, tuple)): # check they are correct items and serialize v = ",".join([ "'{}'".format(field.sanitize_data(si)) if isinstance( si, str) else str(si) for si in v ]) elif v is None: v = field.sanitize_data(v)[1:-1] operator = operator.replace("=", "IS") elif isinstance( v, (datetime.datetime, datetime.date)) or isinstance( field, (CharField)): v = "'{}'".format(v) else: v = field.sanitize_data(v) operator_formater["v"] = v filters.append(bool_string + operator.format(**operator_formater)) return filters