コード例 #1
0
ファイル: metrics.py プロジェクト: xlecours/osf.io
    def _add_metrics(self, queryset_or_obj, method):
        """Parse the ?metric[METRIC]=PERIOD query param, validate it, and
        run ``method`` for each each requested object.

        This is used to share code between add_metric_to_object and get_metrics_queryset.
        """
        metrics_requested = self.parse_metric_query_params(
            self.request.query_params)
        if metrics_requested:
            metric_map = self.metric_map
            for metric, period in metrics_requested.items():
                if metric not in metric_map:
                    raise InvalidQueryStringError(
                        "Invalid metric in query string: '{}'".format(metric),
                        parameter='metrics')
                if period not in self.VALID_METRIC_PERIODS:
                    raise InvalidQueryStringError(
                        "Invalid period for metric: '{}'".format(period),
                        parameter='metrics')
                metric_class = metric_map[metric]
                if period == 'total':
                    after = None
                else:
                    after = timezone.now() - self.TIMEDELTA_MAP[period]
                queryset_or_obj = method(queryset_or_obj, metric_class, metric,
                                         after)
        return queryset_or_obj
コード例 #2
0
ファイル: serializers.py プロジェクト: ccfair/osf.io
    def process_related_counts_parameters(self, params, value):
        """
        Processes related_counts parameter.

        Can either be a True/False value for fetching counts on all fields, or a comma-separated list for specifying
        individual fields.  Ensures field for which we are requesting counts is a relationship field.
        """
        if utils.is_truthy(params) or utils.is_falsy(params):
            return params

        field_counts_requested = [val for val in params.split(',')]

        countable_fields = {field for field in self.parent.fields if
                            getattr(self.parent.fields[field], 'json_api_link', False) or
                            getattr(getattr(self.parent.fields[field], 'field', None), 'json_api_link', None)}
        for count_field in field_counts_requested:
            # Some fields will hide relationships, e.g. HideIfWithdrawal
            # Ignore related_counts for these fields
            fetched_field = self.parent.fields.get(count_field)

            hidden = fetched_field and isinstance(fetched_field, HideIfWithdrawal) and getattr(value, 'is_retracted', False)

            if not hidden and count_field not in countable_fields:
                raise InvalidQueryStringError(
                    detail="Acceptable values for the related_counts query param are 'true', 'false', or any of the relationship fields; got '{0}'".format(
                        params),
                    parameter='related_counts'
                )
        return field_counts_requested
コード例 #3
0
 def get_meta_information(self, meta_data, value):
     """
     For retrieving meta values, otherwise returns {}
     """
     meta = {}
     for key in meta_data or {}:
         if key == 'count':
             show_related_counts = self.context['request'].query_params.get(
                 'related_counts', False)
             if utils.is_truthy(show_related_counts):
                 meta[key] = website_utils.rapply(meta_data[key],
                                                  _url_val,
                                                  obj=value,
                                                  serializer=self.parent)
             elif utils.is_falsy(show_related_counts):
                 continue
             if not utils.is_truthy(show_related_counts):
                 raise InvalidQueryStringError(
                     detail=
                     "Acceptable values for the related_counts query param are 'true' or 'false'; got '{0}'"
                     .format(show_related_counts),
                     parameter='related_counts')
         else:
             meta[key] = website_utils.rapply(meta_data[key],
                                              _url_val,
                                              obj=value,
                                              serializer=self.parent)
     return meta
コード例 #4
0
ファイル: serializers.py プロジェクト: rdhyee/osf.io
    def to_representation(self, value):
        """
        Returns nested dictionary in format {'links': {'self.link_type': ... }

        If no meta information, self.link_type is equal to a string containing link's URL.  Otherwise,
        the link is represented as a links object with 'href' and 'meta' members.
        """
        url = super(JSONAPIHyperlinkedIdentityField,
                    self).to_representation(value)

        meta = {}
        for key in self.meta or {}:
            if key == 'count':
                show_related_counts = self.context['request'].query_params.get(
                    'related_counts', False)
                if utils.is_truthy(show_related_counts):
                    meta[key] = _rapply(self.meta[key],
                                        _url_val,
                                        obj=value,
                                        serializer=self.parent)
                elif utils.is_falsy(show_related_counts):
                    continue
                else:
                    raise InvalidQueryStringError(
                        detail=
                        "Acceptable values for the related_counts query param are 'true' or 'false'; got '{0}'"
                        .format(show_related_counts),
                        parameter='related_counts')
        return {'links': {self.link_type: {'href': url, 'meta': meta}}}
コード例 #5
0
ファイル: serializers.py プロジェクト: ccfair/osf.io
    def to_representation(self, obj, envelope='data'):
        """Serialize to final representation.

        :param obj: Object to be serialized.
        :param envelope: Key for resource object.
        """
        ret = {}
        meta = getattr(self, 'Meta', None)
        type_ = getattr(meta, 'type_', None)
        assert type_ is not None, 'Must define Meta.type_'

        data = {
            'id': '',
            'type': type_,
            'attributes': {},
            'relationships': {},
            'embeds': {},
            'links': {},
        }

        embeds = self.context.get('embed', {})
        context_envelope = self.context.get('envelope', envelope)
        if context_envelope == 'None':
            context_envelope = None
        enable_esi = self.context.get('enable_esi', False)
        is_anonymous = is_anonymized(self.context['request'])
        to_be_removed = set()
        if is_anonymous and hasattr(self, 'non_anonymized_fields'):
            # Drop any fields that are not specified in the `non_anonymized_fields` variable.
            allowed = set(self.non_anonymized_fields)
            existing = set(self.fields.keys())
            to_be_removed = existing - allowed

        fields = [field for field in self.fields.values() if
                  not field.write_only and field.field_name not in to_be_removed]

        invalid_embeds = self.invalid_embeds(fields, embeds)
        invalid_embeds = invalid_embeds - to_be_removed
        if invalid_embeds:
            raise InvalidQueryStringError(parameter='embed',
                                          detail='The following fields are not embeddable: {}'.format(
                                              ', '.join(invalid_embeds)))

        for field in fields:
            try:
                attribute = field.get_attribute(obj)
            except SkipField:
                continue

            nested_field = getattr(field, 'field', None)
            if attribute is None:
                # We skip `to_representation` for `None` values so that
                # fields do not have to explicitly deal with that case.
                data['attributes'][field.field_name] = None
            else:
                try:
                    representation = field.to_representation(attribute)
                except SkipField:
                    continue
                if getattr(field, 'json_api_link', False) or getattr(nested_field, 'json_api_link', False):
                    # If embed=field_name is appended to the query string or 'always_embed' flag is True, directly embed the
                    # results in addition to adding a relationship link
                    if embeds and (field.field_name in embeds or getattr(field, 'always_embed', None)):
                        if enable_esi:
                            try:
                                result = field.to_esi_representation(attribute, envelope=envelope)
                            except SkipField:
                                continue
                        else:
                            try:
                                # If a field has an empty representation, it should not be embedded.
                                result = self.context['embed'][field.field_name](obj)
                            except SkipField:
                                result = None

                        if result:
                            data['embeds'][field.field_name] = result
                        else:
                            data['embeds'][field.field_name] = {'error': 'This field is not embeddable.'}
                    try:
                        if not (is_anonymous and
                                    hasattr(field, 'view_name') and
                                        field.view_name in self.views_to_hide_if_anonymous):
                            data['relationships'][field.field_name] = representation
                    except SkipField:
                        continue
                elif field.field_name == 'id':
                    data['id'] = representation
                elif field.field_name == 'links':
                    data['links'] = representation
                else:
                    data['attributes'][field.field_name] = representation

        if not data['relationships']:
            del data['relationships']

        if not data['embeds']:
            del data['embeds']

        if context_envelope:
            ret[context_envelope] = data
            if is_anonymous:
                ret['meta'] = {'anonymous': True}
        else:
            ret = data
        return ret
コード例 #6
0
    def to_representation(self, obj, envelope='data'):
        """Serialize to final representation.

        :param obj: Object to be serialized.
        :param envelope: Key for resource object.
        """
        ret = {}
        meta = getattr(self, 'Meta', None)
        type_ = getattr(meta, 'type_', None)
        assert type_ is not None, 'Must define Meta.type_'

        data = collections.OrderedDict([
            ('id', ''),
            ('type', type_),
            ('attributes', collections.OrderedDict()),
            ('relationships', collections.OrderedDict()),
            ('embeds', {}),
            ('links', {}),
        ])

        embeds = self.context.get('embed', {})
        fields = [
            field for field in self.fields.values() if not field.write_only
        ]
        invalid_embeds = self.invalid_embeds(fields, embeds)
        if invalid_embeds:
            raise InvalidQueryStringError(
                parameter='embed',
                detail='The following fields are not embeddable: {}'.format(
                    ', '.join(invalid_embeds)))

        for field in fields:
            try:
                attribute = field.get_attribute(obj)
            except SkipField:
                continue

            nested_field = getattr(field, 'field', None)

            if getattr(field, 'json_api_link', False) or getattr(
                    nested_field, 'json_api_link', False):
                # If embed=field_name is appended to the query string or 'always_embed' flag is True, directly embed the
                # results rather than adding a relationship link
                if attribute is None:
                    continue
                if embeds and (field.field_name in embeds
                               or getattr(field, 'always_embed', None)):

                    result = self.context['embed'][field.field_name](obj)
                    if result:
                        data['embeds'][field.field_name] = result
                else:
                    try:
                        data['relationships'][
                            field.field_name] = field.to_representation(
                                attribute)
                    except SkipField:
                        continue
            elif field.field_name == 'id':
                data['id'] = field.to_representation(attribute)
            elif field.field_name == 'links':
                data['links'] = field.to_representation(attribute)
            else:
                if attribute is None:
                    # We skip `to_representation` for `None` values so that
                    # fields do not have to explicitly deal with that case.
                    data['attributes'][field.field_name] = None
                else:
                    data['attributes'][
                        field.field_name] = field.to_representation(attribute)

        if not data['relationships']:
            del data['relationships']

        if not data['embeds']:
            del data['embeds']

        if envelope:
            ret[envelope] = data
        else:
            ret = data
        return ret