Exemple #1
0
    def data(self):
        links = None
        data = []
        included = []
        included_set = set()

        default_type = type_from_model_name(self.default_model.__name__)
        default_serializer = get_schema(default_type)

        for instance in self.collection:
            type_ = type_from_model_name(instance.__class__.__name__)
            serializer_class = get_schema(type_)
            if not issubclass(serializer_class.opts.model, self.base):
                serializer_class = default_serializer

            serialized = serializer_class(instance=instance,
                                          **self.kwargs).data
            if not links and 'links' in serialized:
                links = serialized['links']
            data.append(serialized['data'])
            for include in serialized.get('included', []):
                key = (include['type'], include['id'])
                if key not in included_set:
                    included.append(include)
                    included_set.add(key)

        response = {'data': data}
        if links:
            response['links'] = links
        if included:
            included.sort(key=itemgetter('type', 'id'))
            response['included'] = included

        return order_dict(response, TOP_LEVEL_OBJECT_ORDER)
Exemple #2
0
    def data(self):
        links = None
        data = []
        included = []
        included_set = set()

        default_type = type_from_model_name(self.default_model.__name__)
        default_serializer = get_schema(default_type)

        for instance in self.collection:
            type_ = type_from_model_name(instance.__class__.__name__)
            serializer_class = get_schema(type_)
            if not issubclass(serializer_class.opts.model, self.base):
                serializer_class = default_serializer

            serialized = serializer_class(instance=instance, **self.kwargs).data
            if not links and 'links' in serialized:
                links = serialized['links']
            data.append(serialized['data'])
            for include in serialized.get('included', []):
                key = (include['type'], include['id'])
                if key not in included_set:
                    included.append(include)
                    included_set.add(key)

        response = {
            'data': data
        }
        if links:
            response['links'] = links
        if included:
            included.sort(key=itemgetter('type', 'id'))
            response['included'] = included

        return order_dict(response, TOP_LEVEL_OBJECT_ORDER)
Exemple #3
0
    def __new__(cls, base, default_model, instance=None, data=None, many=False,
                **kwargs):
        if not many:
            # in the single instance case return the correct serializer by type
            # or the default_model's serializer if type is not valid for base
            type_ = None
            if instance:
                type_ = type_from_model_name(instance.__class__.__name__)
            elif data:
                type_ = data.get('data', {}).get('type')

            if type_:
                serializer_class = get_schema(type_)
                if not issubclass(serializer_class.opts.model, base):
                    type_ = None

            if not type_:
                type_ = type_from_model_name(default_model.__name__)
                serializer_class = get_schema(type_)

            return serializer_class(
                instance=instance, data=data, many=many, **kwargs)

        if data:
            raise ValueError(
                u"You can only use a JsonApiPolymorphicSerializer with "
                u"many=True for serializing a ModelCollection")

        return super(JsonApiPolymorphicSerializer, cls).__new__(
            cls, base, default_model, instance, data, many, **kwargs)
Exemple #4
0
 def add_includes(self, includes):
     included_data = self.included_data
     for instance in includes:
         type_ = type_from_model_name(instance.__class__.__name__)
         serializer = get_schema(type_)(instance,
                                        fields_map=self.fields_map,
                                        exclude_map=self.exclude_map)
         data = serializer.data
         item = data['data']
         included_data[(item['type'], item['id'])] = item
         included_data.update(serializer.included_data)
Exemple #5
0
    def format_profile_references(self, instances):
        references = []
        for instance in instances:
            type_ = type_from_model_name(instance.__class__.__name__)
            serializer = get_schema(type_)(instance.with_snapshots(
                ('working', )),
                                           only=('id', ))
            data = serializer.data.get('data', {})
            if data:
                references.append(data)

        return references
Exemple #6
0
    def format_profile_references(self, instances):
        references = []
        for instance in instances:
            type_ = type_from_model_name(instance.__class__.__name__)
            serializer = get_schema(type_)(
                instance.with_snapshots(('working',)),
                only=('id',))
            data = serializer.data.get('data', {})
            if data:
                references.append(data)

        return references
Exemple #7
0
 def add_includes(self, includes):
     included_data = self.included_data
     for instance in includes:
         type_ = type_from_model_name(instance.__class__.__name__)
         serializer = get_schema(type_)(
             instance,
             fields_map=self.fields_map,
             exclude_map=self.exclude_map)
         data = serializer.data
         item = data['data']
         included_data[(item['type'], item['id'])] = item
         included_data.update(serializer.included_data)
Exemple #8
0
    def __new__(cls,
                base,
                default_model,
                instance=None,
                data=None,
                many=False,
                **kwargs):
        if not many:
            # in the single instance case return the correct serializer by type
            # or the default_model's serializer if type is not valid for base
            type_ = None
            if instance:
                type_ = type_from_model_name(instance.__class__.__name__)
            elif data:
                type_ = data.get('data', {}).get('type')

            if type_:
                serializer_class = get_schema(type_)
                if not issubclass(serializer_class.opts.model, base):
                    type_ = None

            if not type_:
                type_ = type_from_model_name(default_model.__name__)
                serializer_class = get_schema(type_)

            return serializer_class(instance=instance,
                                    data=data,
                                    many=many,
                                    **kwargs)

        if data:
            raise ValueError(
                u"You can only use a JsonApiPolymorphicSerializer with "
                u"many=True for serializing a ModelCollection")

        return super(JsonApiPolymorphicSerializer,
                     cls).__new__(cls, base, default_model, instance, data,
                                  many, **kwargs)
Exemple #9
0
    def load_profile_updates(self):
        if UPDATES_PROFILE not in self.initial_data.get('links',
                                                        {}).get('profile', []):
            return [], []
        for alias, profile in iteritems(self.initial_data.get('aliases', {})):
            if profile == UPDATES_PROFILE:
                break
        else:
            return [], []

        errors = []
        validated_data = []
        profile_serializers = []
        for i, update in enumerate(
                self.initial_data.get('meta', {}).get(alias, [])):
            if 'type' not in update:
                errors.append({
                    'detail': '`data` object must include `type` key.',
                    'source': {
                        'pointer': '/meta/{}/{}/data'.format(alias, i)
                    }
                })
                continue

            type_ = update['type']
            data = {
                'data': update,
            }

            try:
                serializer_class = get_schema(type_)
            except ImproperlyConfigured:
                errors.append({
                    'detail': 'Invalid type: {}.'.format(type_),
                    'source': {
                        'pointer': '/meta/{}/{}/data/type'.format(alias, i),
                    },
                })
                continue

            serializer = serializer_class(
                data=data,
                partial=set(
                    serializer_class.opts.model._ordered_fields).difference(
                        {'id'}))

            try:
                validated_data.append(serializer.validated_data)
                profile_serializers.append(serializer)
            except (ValidationError, IncorrectTypeError) as err:
                errors.extend({
                    'detail': error['detail'],
                    'source': {
                        'pointer':
                        '/meta/{}/{}{}'.format(alias, i, error['source']
                                               ['pointer'])
                    },
                } for error in err.messages.get('errors', []))
                continue

        if errors:
            err = ValidationError(u'Invalid data for updates.')
            err.messages = {'errors': errors}
            raise err

        return validated_data, profile_serializers
 def schema(self):
     schema = self._serializer or get_schema(self.type_)
     return schema(fields_map=self.root.fields_map,
                   exclude_map=self.root.exclude_map,
                   include_data=self.root.include_map.get(self.name, []),
                   include_data_map=self.root.include_data_map)
Exemple #11
0
 def schema(self):
     schema = self._serializer or get_schema(self.type_)
     return schema(fields_map=self.root.fields_map,
                   exclude_map=self.root.exclude_map,
                   include_data=self.root.include_map.get(self.name, []),
                   include_data_map=self.root.include_data_map)
Exemple #12
0
    def load_profile_updates(self):
        if UPDATES_PROFILE not in self.initial_data.get(
                'links', {}).get('profile', []):
            return [], []
        for alias, profile in iteritems(self.initial_data.get('aliases', {})):
            if profile == UPDATES_PROFILE:
                break
        else:
            return [], []

        errors = []
        validated_data = []
        profile_serializers = []
        for i, update in enumerate(
                self.initial_data.get('meta', {}).get(alias, [])):
            if 'type' not in update:
                errors.append({
                    'detail': '`data` object must include `type` key.',
                    'source': {
                        'pointer': '/meta/{}/{}/data'.format(alias, i)
                    }
                })
                continue

            type_ = update['type']
            data = {
                'data': update,
            }

            try:
                serializer_class = get_schema(type_)
            except ImproperlyConfigured:
                errors.append({
                    'detail': 'Invalid type: {}.'.format(type_),
                    'source': {
                        'pointer': '/meta/{}/{}/data/type'.format(alias, i),
                    },
                })
                continue

            serializer = serializer_class(
                data=data,
                partial=set(
                    serializer_class.opts.model._ordered_fields).difference(
                        {'id'}))

            try:
                validated_data.append(serializer.validated_data)
                profile_serializers.append(serializer)
            except (ValidationError, IncorrectTypeError) as err:
                errors.extend({
                    'detail': error['detail'],
                    'source': {
                        'pointer': '/meta/{}/{}{}'.format(
                            alias, i, error['source']['pointer'])
                    },
                } for error in err.messages.get('errors', []))
                continue

        if errors:
            err = ValidationError(u'Invalid data for updates.')
            err.messages = {
                'errors': errors
            }
            raise err

        return validated_data, profile_serializers