def _update_excluded_with_related_not_required( cls, exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None], nested: bool = False, ) -> Union[Set, Dict]: """ Used during generation of the dict(). To avoid cyclical references and max recurrence limit nested models have to exclude related models that are not mandatory. For a main model (not nested) only nullable related field names are added to exclusion, for nested models all related models are excluded. :param exclude: set/dict with fields to exclude :type exclude: Union[Set, Dict, None] :param nested: flag setting nested models (child of previous one, not main one) :type nested: bool :return: set or dict with excluded fields added. :rtype: Union[Set, Dict] """ exclude = exclude or {} related_set = cls._exclude_related_names_not_required(nested=nested) if isinstance(exclude, set): exclude.union(related_set) else: related_dict = translate_list_to_dict(related_set) exclude = update(related_dict, exclude) return exclude
def test_updating_dict_inc_set_with_dict_inc_set(): curr_dict = { "aa": Ellipsis, "bb": Ellipsis, "cc": { "aa": {"xx", "yy"}, "bb": Ellipsis }, } dict_to_update = { "uu": Ellipsis, "bb": {"cc", "dd"}, "cc": { "aa": {"xx", "oo", "zz", "ii"} }, } test = update(curr_dict, dict_to_update) assert test == { "aa": Ellipsis, "bb": {"cc", "dd"}, "cc": { "aa": {"xx", "yy", "oo", "zz", "ii"}, "bb": Ellipsis }, "uu": Ellipsis, }
def _update_excluded_with_related_not_required( cls, exclude: Union["AbstractSetIntStr", "MappingIntStrAny", None], nested: bool = False, ) -> Union[Set, Dict]: exclude = exclude or {} related_set = cls._exclude_related_names_not_required(nested=nested) if isinstance(exclude, set): exclude.union(related_set) else: related_dict = translate_list_to_dict(related_set) exclude = update(related_dict, exclude) return exclude
def exclude_fields(self, columns: Union[List, str, Set, Dict]) -> "QuerySet": """ With `exclude_fields()` you can select subset of model columns that will be excluded to limit the data load. It's the opposite of `fields()` method so check documentation above to see what options are available. Especially check above how you can pass also nested dictionaries and sets as a mask to exclude fields from whole hierarchy. Note that `fields()` and `exclude_fields()` works both for main models (on normal queries like `get`, `all` etc.) as well as `select_related` and `prefetch_related` models (with nested notation). Mandatory fields cannot be excluded as it will raise `ValidationError`, to exclude a field it has to be nullable. Pk column cannot be excluded - it's always auto added even if explicitly excluded. :param columns: columns to exclude :type columns: Union[List, str, Set, Dict] :return: QuerySet :rtype: QuerySet """ if isinstance(columns, str): columns = [columns] current_excluded = self._exclude_columns if not isinstance(columns, dict): current_excluded = update_dict_from_list(current_excluded, columns) else: current_excluded = update(current_excluded, columns) return self.__class__( model_cls=self.model, filter_clauses=self.filter_clauses, exclude_clauses=self.exclude_clauses, select_related=self._select_related, limit_count=self.limit_count, offset=self.query_offset, columns=self._columns, exclude_columns=current_excluded, order_bys=self.order_bys, prefetch_related=self._prefetch_related, limit_raw_sql=self.limit_sql_raw, )
def fields(self, columns: Union[List, str, Set, Dict]) -> "QuerySet": if isinstance(columns, str): columns = [columns] current_included = self._columns if not isinstance(columns, dict): current_included = update_dict_from_list(current_included, columns) else: current_included = update(current_included, columns) return self.__class__( model_cls=self.model, filter_clauses=self.filter_clauses, exclude_clauses=self.exclude_clauses, select_related=self._select_related, limit_count=self.limit_count, offset=self.query_offset, columns=current_included, exclude_columns=self._exclude_columns, order_bys=self.order_bys, )
def fields(self, columns: Union[List, str, Set, Dict]) -> "QuerySet": """ With `fields()` you can select subset of model columns to limit the data load. Note that `fields()` and `exclude_fields()` works both for main models (on normal queries like `get`, `all` etc.) as well as `select_related` and `prefetch_related` models (with nested notation). You can select specified fields by passing a `str, List[str], Set[str] or dict` with nested definition. To include related models use notation `{related_name}__{column}[__{optional_next} etc.]`. `fields()` can be called several times, building up the columns to select. If you include related models into `select_related()` call but you won't specify columns for those models in fields - implies a list of all fields for those nested models. Mandatory fields cannot be excluded as it will raise `ValidationError`, to exclude a field it has to be nullable. Pk column cannot be excluded - it's always auto added even if not explicitly included. You can also pass fields to include as dictionary or set. To mark a field as included in a dictionary use it's name as key and ellipsis as value. To traverse nested models use nested dictionaries. To include fields at last level instead of nested dictionary a set can be used. To include whole nested model specify model related field name and ellipsis. :param columns: columns to include :type columns: Union[List, str, Set, Dict] :return: QuerySet :rtype: QuerySet """ if isinstance(columns, str): columns = [columns] current_included = self._columns if not isinstance(columns, dict): current_included = update_dict_from_list(current_included, columns) else: current_included = update(current_included, columns) return self.__class__( model_cls=self.model, filter_clauses=self.filter_clauses, exclude_clauses=self.exclude_clauses, select_related=self._select_related, limit_count=self.limit_count, offset=self.query_offset, columns=current_included, exclude_columns=self._exclude_columns, order_bys=self.order_bys, prefetch_related=self._prefetch_related, limit_raw_sql=self.limit_sql_raw, )