def typed_val(val): """ 将字符串转为对应类型对象 根据特征明显程度:list -> float, int -> bool -> str """ if val is None: return b = str2bool(val, silent=True) if is_list(val): return json.loads(val) elif is_float(val): return float(val) elif is_int(val): return int(val) elif b is not None: return b elif isinstance(val, str): return val raise forms.ValidationError( _('Type error, choices are int, float, str, list, bool or None.'))
def _clean_query_value(value, field=None, refer_value=None, iterable=False): """ value_type is used for MongoDB data """ if value == 'null': return None if iterable: # 转为可迭代对象 value = str2iter(value) try: if isinstance(field, models.DateTimeField) or isinstance( refer_value, datetime.datetime): value = list( map(lambda x: to_aware_datetime(x), value)) if iterable else to_aware_datetime(value) elif isinstance(field, models.BooleanField) or isinstance( refer_value, bool): if iterable: # bool filed not support iterable value raise InvalidParameter(value) value = str2bool(value) elif isinstance(field, models.IntegerField) or isinstance( refer_value, int): value = list(map(lambda x: int(x), value)) if iterable else str2int(value) elif isinstance(field, models.FloatField) or isinstance( refer_value, float): value = list(map(lambda x: float(x), value)) if iterable else str2float(value) else: # str, bson ... pass except Exception: raise InvalidParameter(value) return value
def __getattr__(self, item): """ 通过注解类型获取配置的值 """ options = self.__annotations__.keys() if item not in options: logger.warning("No such options defined in section [%s]." % self.section) raise AttributeError("No such options defined in section [%s]." % self.section) for option, a_type in self.__annotations__.items(): if item == option: value = None try: value = parser.get(self.section, option) except Exception as e: logger.warning("配置文件属性获取错误", e) if a_type is bool: return str2bool(value) if value is None: return value return a_type.__call__(value) return super().__getattribute__(item)
def _filter_queryset(self, queryset): """ Filter queryset by layer, then by filter parameters and order queryset if necessary """ # filtering except in case of passing parameter all=true query_data = self.request.GET if queryset.exists(): ordering = self.get_ordering() if self.paginator_class is Paginator: meta = queryset[0]._meta fields = chain(meta.concrete_fields, meta.many_to_many) # try to get filters conditions = dict() exclude_cond = dict() for i, f in enumerate(fields): name = f.attname ff = self.FilterFormat(name) if query_data.get(ff.isin): conditions[ff.isin] = self._clean_query_value( query_data.get(ff.isin), f, iterable=True) if query_data.get(ff.range): value = self._clean_query_value(query_data.get( ff.range), f, iterable=True) if isinstance(value, str) or len(value) != 2: raise InvalidParameter( _('Range must be a list with two elements.')) conditions[ff.range] = value if query_data.get(ff.isnull): try: cleaned_value = str2bool(query_data.get(ff.isnull)) except (TypeError, ValueError): raise InvalidParameter( _('isnull accepts only bool type')) conditions[ff.isnull] = cleaned_value common_cond = (ff.exact, ff.iexact, ff.contains, ff.icontains, ff.gt, ff.gte, ff.lt, ff.lte) for item in common_cond: if query_data.get(item): conditions[item] = self._clean_query_value( query_data.get(item), f) elif query_data.get(ff.exclude(item)): exclude_cond[item] = self._clean_query_value( query_data.get(ff.exclude(item)), f) queryset = queryset.exclude(**exclude_cond).filter( **conditions) if ordering: if isinstance(ordering, str): ordering = (ordering, ) queryset = queryset.order_by(*ordering) self.total_length = queryset.count() elif self.paginator_class is MongoPaginator: conditions = dict() # col = getattr(self, 'collection') first_item = queryset.find_one() if first_item: for name, v in first_item.items(): ff = self.FilterFormat(name) if query_data.get(ff.isin): value = self._clean_query_value(query_data.get( ff.isin), refer_value=v, iterable=True) conditions[name] = {'$in': value} elif query_data.get(ff.range): value = self._clean_query_value(query_data.get( ff.range), refer_value=v, iterable=True) if isinstance(value, str) or len(value) != 2: raise InvalidParameter( _('Range must be a list with two elements.' )) _cond = {'$gte': value[0], '$lte': value[1]} conditions.update({name: _cond}) elif query_data.get(ff.isnull): value = str2bool(query_data.get(ff.isnull)) conditions.update({name: value}) for item in (ff.exact, ff.gt, ff.gte, ff.lt, ff.lte, ff.contains): if query_data.get(item): value = self._clean_query_value( query_data.get(item), refer_value=v) if item == ff.exact: conditions.update({name: value}) else: _cond = dict() if item == ff.gt: _cond.update({'$gt': value}) elif item == ff.gte: _cond.update({'$gte': value}) elif item == ff.lt: _cond.update({'$lt': value}) elif item == ff.lte: _cond.update({'$lte': value}) elif item == ff.contains: _cond.update({'$regex': value}) conditions.update({name: _cond}) if item in (ff.icontains, ff.iexact): if query_data.get(item): raise InvalidParameter(_('')) # conditions.update({'object_name': {'$ne': ''}}) queryset = queryset.find(conditions) if queryset: if ordering: if ordering.startswith('-'): queryset = queryset.sort(ordering[1:], -1) else: queryset = queryset.sort(ordering) return queryset
def get_show_all(self): self.show_all = str2bool(self.request.GET.get('all', False)) return self.show_all