Exemplo n.º 1
0
    def _update_flattened_field(self,
                                validated_data,
                                instance=None,
                                related_objects=None):
        assert not (instance and related_objects
                    ), "cannot pass both instance and related_objects"
        for field_name, (serializer_class,
                         source) in self._flattened_fields.items():
            if field_name in validated_data:
                partial = self.partial
                try:
                    obj = get_attribute(instance, source.split('.'))
                except (AttributeError, KeyError):
                    obj = get_attribute(related_objects, source.split('.'))
                    partial = True
                except (AttributeError, KeyError):
                    obj = None

                serializer = serializer_class(
                    instance=obj,
                    data=validated_data.pop(field_name),
                    context=self.context,
                    partial=partial)
                serializer.is_valid(raise_exception=True)
                serializer.save()
Exemplo n.º 2
0
 def get_attribute(self, instance):
     # We customize `get_attribute` here for performance reasons.
     # For relationships the instance will already have the pk of
     # the related object. We return this directly instead of returning the
     # object itself, which would require a database lookup.
     try:
         instance = get_attribute(instance, self.source_attrs[:-1])
         return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1]))
     except AttributeError:
         return get_attribute(instance, self.source_attrs)
Exemplo n.º 3
0
 def extract_lookup(self, instance, key, lookup) -> Any:
     lookup_path = lookup.split('.')
     if lookup_path[0] == 'self':
         return get_attribute(
             self.parent.instance,
             lookup_path[1:]
         )
     else:
         return get_attribute(
             instance, lookup_path
         )
 def get_attribute(self, instance):
     # We customize `get_attribute` here for performance reasons.
     # For relationships the instance will already have the pk of
     # the related object. We return this directly instead of returning the
     # object itself, which would require a database lookup.
     try:
         instance = get_attribute(instance, self.source_attrs[:-1])
         return PKOnlyObject(
             pk=instance.serializable_value(self.source_attrs[-1]))
     except AttributeError:
         return get_attribute(instance, self.source_attrs)
Exemplo n.º 5
0
    def get_attribute(self, instance):
        if self.use_pk_only_optimization() and self.source_attrs:
            # Optimized case, return a mock object only containing the pk attribute.
            try:
                instance = get_attribute(instance, self.source_attrs[:-1])
                return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1]))
            except AttributeError:
                pass

        # Standard case, return the object instance.
        return get_attribute(instance, self.source_attrs)
Exemplo n.º 6
0
    def get_attribute(self, instance):
        if self.use_pk_only_optimization() and self.source_attrs:
            # Optimized case, return a mock object only containing the pk attribute.
            try:
                instance = get_attribute(instance, self.source_attrs[:-1])
                return PKOnlyObject(
                    pk=instance.serializable_value(self.source_attrs[-1]))
            except AttributeError:
                pass

        # Standard case, return the object instance.
        return get_attribute(instance, self.source_attrs)
Exemplo n.º 7
0
 def process_source(self, object_list, source):
     new_object_list = []
     for obj in object_list:
         value = obj
         value = get_attribute(value, source.split('.'))
         new_object_list.append(value)
     return new_object_list
Exemplo n.º 8
0
    def get_attribute(self, instance):
        # Can't have any relationships if not created
        if hasattr(instance, 'pk') and instance.pk is None:
            return []

        relationship = get_attribute(instance, self.source_attrs)
        return relationship.all() if (hasattr(relationship, 'all')) else relationship
Exemplo n.º 9
0
    def get_attribute(self, instance):
        # Can't have any relationships if not created
        if hasattr(instance, "pk") and instance.pk is None:
            return []

        relationship = get_attribute(instance, self.source_attrs)
        return relationship.all() if hasattr(relationship, "all") else relationship
Exemplo n.º 10
0
    def get_attribute(self, instance):
        # Can't have any relationships if not created
        if not instance.pk:
            return []

        relationship = get_attribute(instance, self.source_attrs)
        return relationship.all() if (hasattr(relationship, "all")) else relationship
Exemplo n.º 11
0
    def _get_related_model_field(self, nested_serializer):
        """Return model field through that nested serializer relate with
        parent and type of relation.
        :param nested_serializer:
        :return: Tuple contained model field and relation type
        (`forward`, `reverse`).
        """
        assert len(nested_serializer.source_attrs) == 1, "We don't support fields with complex source."

        related_descriptor = get_attribute(
            self.Meta.model,
            nested_serializer.source_attrs
        )

        if isinstance(related_descriptor, related_descriptors.ReverseOneToOneDescriptor):
            return related_descriptor.related.field, 'forward'
        if isinstance(related_descriptor, related_descriptors.ReverseManyToOneDescriptor):
            return related_descriptor.field, 'forward'
        if (isinstance(
                related_descriptor,
                related_descriptors.ForwardManyToOneDescriptor
        ) and isinstance(related_descriptor.field, related.OneToOneField)):
            return related_descriptor.field, 'reverse'

        assert False, "We don't support many to many relation and forward many to one " \
                      "because updating this relation have side effect."
Exemplo n.º 12
0
    def get_attribute(self, instance):
        if self.use_pk_only_optimization() and self.source_attrs:
            # Optimized case, return a mock object only containing the pk attribute.
            try:
                instance = get_attribute(instance, self.source_attrs[:-1])
                value = instance.serializable_value(self.source_attrs[-1])
                if is_simple_callable(value):
                    # Handle edge case where the relationship `source` argument
                    # points to a `get_relationship()` method on the model
                    value = value().pk
                return PKOnlyObject(pk=value)
            except AttributeError:
                pass

        # Standard case, return the object instance.
        return get_attribute(instance, self.source_attrs)
Exemplo n.º 13
0
def get_attribute_smart(instance, attrs):
    """A bit smarter version of rest_framework.fields.get_attribute.
    Has ability to work with lists, so it can be used to look deep inside relations.
    Also is suitable for dicts.

    Example usage:

    get_attribute_smart({"instances": [{"id": 1}, {"id": 2}, {"id": 3}]}, "instances.id")
    """

    if instance is None or not attrs:
        return instance

    if isinstance(attrs, six.string_types):
        attrs = attrs.split('.')

    if isinstance(
            instance,
        (Iterable, QuerySet)) and not isinstance(instance,
                                                 (Mapping, six.string_types)):
        instance = list(
            [get_attribute_smart(obj, [attrs[0]]) for obj in instance])
        if all(map(lambda obj: isinstance(obj, QuerySet), instance)):
            instance = chain(*instance)
    else:
        instance = get_attribute(instance, [attrs[0]])

        if isinstance(instance, Manager):
            instance = instance.all()

    return get_attribute_smart(instance, attrs[1:])
Exemplo n.º 14
0
    def to_representation(self, instance):

        agg_op = self.get_agg_op(instance)
        real_instance = self.get_real_instance(instance)
        child = self.resolve_child_type(real_instance, agg_op)

        transformed_instance = {'aggregates': real_instance}

        for field, (field_serializer,
                    initial) in self.get_aggregate_types_and_defaults(
                        real_instance, agg_op).items():
            transformed_instance[self.get_aggregate_field_name(
                field, real_instance, agg_op)] = initial
            self.fields[self.get_aggregate_field_name(
                field, real_instance, agg_op)] = field_serializer

        for obj in real_instance:
            for field in self.get_aggregate_types_and_defaults(
                    real_instance, agg_op):
                value = get_attribute(obj, [field])
                transformed_instance[self.get_aggregate_field_name(
                    field, real_instance, agg_op)] = self.top_level_reduce(
                        transformed_instance[self.get_aggregate_field_name(
                            field, real_instance, agg_op)],
                        value,
                    )

        self.fields['aggregates'] = serializers.ListField(child=child, )

        return super(AggregateListSerializer,
                     self).to_representation(transformed_instance)
Exemplo n.º 15
0
def _get_attribute(self, instance):
    # Can't have any relationships if not created
    if hasattr(instance, 'pk') and instance.pk is None:
        return []

    try:
        relationship = get_attribute(instance, self.source_attrs)
    except (KeyError, AttributeError) as exc:
        if self.default is not empty:
            return self.get_default()
        if self.allow_null:
            return None
        if not self.required:
            raise SkipField()
        msg = ('Got {exc_type} when attempting to get a value for field '
               '`{field}` on serializer `{serializer}`.\nThe serializer '
               'field might be named incorrectly and not match '
               'any attribute or key on the `{instance}` instance.\n'
               'Original exception text was: {exc}.'.format(
                   exc_type=type(exc).__name__,
                   field=self.field_name,
                   serializer=self.parent.__class__.__name__,
                   instance=instance.__class__.__name__,
                   exc=exc,
               ))
        raise type(exc)(msg)

    return relationship.all() if hasattr(relationship, 'all') else relationship
Exemplo n.º 16
0
    def get_attribute(self, instance):
        if self.use_pk_only_optimization() and self.source_attrs:
            # Optimized case, return a mock object only containing the pk attribute.
            try:
                instance = get_attribute(instance, self.source_attrs[:-1])
                value = instance.serializable_value(self.source_attrs[-1])
                if is_simple_callable(value):
                    # Handle edge case where the relationship `source` argument
                    # points to a `get_relationship()` method on the model
                    value = value().pk
                return PKOnlyObject(pk=value)
            except AttributeError:
                pass

        # Standard case, return the object instance.
        return get_attribute(instance, self.source_attrs)
Exemplo n.º 17
0
    def get(self, request):
        user = request.user

        forms_context_dict = {}
        form_class_context_key_user_field_tuples = [
            [InstituteAddressForm, 'insti_address_form', ('insti_address',)],
            [ProgramForm, 'program_form', ('program',)],
            [SexUpdateForm, 'sex_update_form', ('userprofile', 'sex',)],
        ]

        for form_class, context_key, user_attr in form_class_context_key_user_field_tuples:
            try:
                form = form_class(initial=attr_to_dict(get_attribute(user, user_attr), key=user_attr[-1]))
            except (AttributeError, ObjectDoesNotExist):
                form = form_class()
            forms_context_dict[context_key] = form

        mobile_numbers = ContactNumber.objects.all().filter(user=user).order_by('-id')
        secondary_emails = SecondaryEmail.objects.all().filter(user=user).order_by('-id')
        user_profile = user.userprofile
        gpo_email = user.email
        ldap_number = user_profile.mobile
        roll_number = user_profile.roll_number

        request_context = {
            'mobile_numbers': mobile_numbers,
            'secondary_emails': secondary_emails,
            'gpo_email': gpo_email,
            'ldap_number': ldap_number,
            'roll_number': roll_number,
            'user_profile_picture': model_field_media_url(user.userprofile.profile_picture),
        }
        request_context.update(forms_context_dict)

        return render(request, 'user_resources/home.html', request_context)
    def get_attribute(self, instance):
        # Can't have any relationships if not created
        if not instance.pk:
            return []

        relationship = get_attribute(instance, self.source_attrs)
        return relationship.all() if (hasattr(relationship,
                                              'all')) else relationship
Exemplo n.º 19
0
 def get_url(self, obj, view_name, request, format):
     if hasattr(obj, 'pk') and obj.pk is None:
         return None
     lookup_url_kwargs = {}
     for lookup_field, lookup_url_kwarg in zip(self.lookup_fields, self.lookup_url_kwargs):
         lookup_value = get_attribute(obj, lookup_field.replace('__', '.').split('.'))
         lookup_url_kwargs[lookup_url_kwarg] = lookup_value
     return self.reverse(view_name, kwargs=lookup_url_kwargs, request=request, format=format)
Exemplo n.º 20
0
 def should_redact(self, instance, context=None):
     if self.user_field and self.parent:
         request = (context or self.context).get("request", None)
         if request and hasattr(request, "user"):
             user = get_attribute(instance, self.user_field.split("."))
             return not request.user.id is user.id
         return True
     else:
         return False
Exemplo n.º 21
0
        def get_attribute_override(self, instance):
            # Override the default implementation of get_attribute
            # Can't have any relationships if not created
            if hasattr(instance, 'pk') and instance.pk is None:
                return []

            relationship = get_attribute(instance, self.source_attrs)
            queryset = filter_relationship(self, instance, relationship)
            return queryset.all() if (hasattr(queryset, 'all')) else queryset
Exemplo n.º 22
0
    def get_url(self, obj, view_name, request, format):
        url = super().get_url(obj, view_name, request, format)

        if url and self.__query_params:
            get = lambda x: x(obj) if callable(x) else get_attribute(obj, x.split('.'))
            params = [(key, get(value)) for key, value in self.__query_params.items()]
            url = url + '?' + urlencode(params)

        return url
Exemplo n.º 23
0
 def get_attribute(self, instance):
     """
     Given the *outgoing* object instance, return the primitive value
     that should be used for this field.
     """
     try:
         return fields.get_attribute(instance, self.source_attrs)
     except (KeyError, AttributeError) as exc:
         return None if self.default == fields.empty else self.default
Exemplo n.º 24
0
    def __call__(self, new_value):
        # no instance -> it's not an update
        if not self.instance:
            return

        current_value = get_attribute(self.instance,
                                      self.serializer_field.source_attrs)

        if new_value != current_value:
            raise serializers.ValidationError(self.message, code=self.code)
Exemplo n.º 25
0
    def get_owner_of(self, obj):
        try:
            meta = getattr(self, 'Meta', None)
            owner_attr = getattr(meta, 'owner_attr')
        except KeyError:
            return None

        if owner_attr == '*':
            return obj

        return get_attribute(obj, owner_attr.split('.'))
Exemplo n.º 26
0
    def update(self, instance, validated_data):
        if isinstance(instance, models.Manager):
            instance = instance.all()
        exists_instances = {i.pk: i for i in instance}
        excess_instances_pks = set(exists_instances.keys())

        model = self.child.Meta.model

        result = list()
        errors = list()
        has_error = False
        for data in validated_data:
            errors.append(dict())

            # PK used to detect exists objects.
            try:
                pk = get_attribute(data, self.child.pk_field.source_attrs)
            except KeyError:
                pk = None

            try:

                if pk:
                    if pk not in exists_instances:
                        raise serializers.ValidationError({
                            self.child.pk_field.field_name:
                            _('{} with pk `{}` doesn\'t exists.').format(
                                model._meta.verbose_name.title(), pk),
                        })

                    if pk not in excess_instances_pks:
                        raise serializers.ValidationError({
                            self.child.pk_field.field_name:
                            _('Duplication {} with pk `{}`.').format(
                                model._meta.verbose_name, pk)
                        })
                    excess_instances_pks.remove(pk)

                    result.append(self.child.update(exists_instances[pk],
                                                    data))
                else:
                    result.append(self.child.create(data))

            except serializers.ValidationError as exc:
                has_error = True
                errors[-1] = serializers.as_serializer_error(exc)

        if has_error:
            raise serializers.ValidationError(errors)

        if excess_instances_pks and not getattr(self.root, 'partial', False):
            model._default_manager.filter(pk__in=excess_instances_pks).delete()

        return result
    def get_related_instance(self):
        parent_obj = self.get_object()
        parent_serializer = self.serializer_class(parent_obj)
        field_name = self.get_related_field_name()
        field = parent_serializer.fields.get(field_name, None)

        if field is not None:
            try:
                instance = field.get_attribute(parent_obj)
            except SkipField:
                instance = get_attribute(parent_obj, field.source_attrs)
            else:
                if isinstance(instance, PKOnlyObject):
                    # need whole object
                    instance = get_attribute(parent_obj, field.source_attrs)
            return instance
        else:
            try:
                return getattr(parent_obj, field_name)
            except AttributeError:
                raise NotFound
Exemplo n.º 28
0
    def get_related_instance(self):
        parent_obj = self.get_object()
        parent_serializer = self.serializer_class(parent_obj)
        field_name = self.get_related_field_name()
        field = parent_serializer.fields.get(field_name, None)

        if field is not None:
            try:
                instance = field.get_attribute(parent_obj)
            except SkipField:
                instance = get_attribute(parent_obj, field.source_attrs)
            else:
                if isinstance(instance, PKOnlyObject):
                    # need whole object
                    instance = get_attribute(parent_obj, field.source_attrs)
            return instance
        else:
            try:
                return getattr(parent_obj, field_name)
            except AttributeError:
                raise NotFound
Exemplo n.º 29
0
    def get_attribute(self, instance):
        # Can't have any relationships if not created.
        if hasattr(instance, 'pk') and instance.pk is None:
            return []

        queryset = self.queryset
        if hasattr(queryset, '__call__'):
            queryset = queryset(self.child_relation, instance)
        else:
            relationship = get_attribute(instance, self.source_attrs)
            queryset = relationship.all() if (hasattr(relationship, 'all')) else relationship
        return queryset
Exemplo n.º 30
0
 def get_attribute(self, obj, requested_language=None):
     source = self.source or self.field_name
     field = fields.get_attribute(obj, source.split("."))
     if not field:
         return None
     request = self.context.get("request", None)
     if requested_language is None:
         if request and request.method == "GET" and "lang" in request.GET:
             requested_language = request.GET["lang"]
     if requested_language:
         return self.fetch_single_translation(obj, source, field, requested_language)
     else:
         return self.fetch_all_translations(obj, source, field)
    def extract_relation_instance(cls, field, resource_instance):
        """
        Determines what instance represents given relation and extracts it.

        Relation instance is determined exactly same way as it determined
        in parent serializer
        """
        try:
            res = field.get_attribute(resource_instance)
            if isinstance(res, PKOnlyObject):
                return get_attribute(resource_instance, field.source_attrs)
            return res
        except SkipField:
            return None
Exemplo n.º 32
0
    def get_url(self, obj, view_name, request, format):  # pylint: disable=redefined-builtin

        # Unsaved objects will not yet have a valid URL.
        if hasattr(obj, 'pk') and obj.pk in (None, ''):
            return None

        if self.lookup_fields:
            kwargs = {
                key: get_attribute(obj, value.split('__')) for key, value
                in zip(self.lookup_url_kwargs, self.lookup_fields)
            }
            return self.reverse(view_name, kwargs=kwargs, request=request, format=format)

        return super().get_url(obj, view_name, request, format)
Exemplo n.º 33
0
 def get_attribute(self, obj, requested_language=None):
     source = self.source or self.field_name
     field = fields.get_attribute(obj, source.split('.'))
     if not field:
         return None
     request = self.context.get('request', None)
     if requested_language is None:
         if request and request.method == 'GET' and 'lang' in request.GET:
             requested_language = request.GET['lang']
     if requested_language:
         return self.fetch_single_translation(obj, source, field,
                                              requested_language)
     else:
         return self.fetch_all_translations(obj, source, field)
Exemplo n.º 34
0
    def get(self, request):
        user = request.user

        forms_context_dict = {}
        form_class_context_key_user_field_tuples = [
            [InstituteAddressForm, 'insti_address_form', ('insti_address', )],
            [ProgramForm, 'program_form', ('program', )],
            [SexUpdateForm, 'sex_update_form', (
                'userprofile',
                'sex',
            )],
        ]

        for form_class, context_key, user_attr in form_class_context_key_user_field_tuples:
            try:
                form = form_class(initial=attr_to_dict(
                    get_attribute(user, user_attr), key=user_attr[-1]))
            except (AttributeError, ObjectDoesNotExist):
                form = form_class()
            forms_context_dict[context_key] = form

        mobile_numbers = ContactNumber.objects.all().filter(
            user=user).order_by('-id')
        secondary_emails = SecondaryEmail.objects.all().filter(
            user=user).order_by('-id')
        user_profile = user.userprofile
        gpo_email = user.email
        ldap_number = user_profile.mobile
        roll_number = user_profile.roll_number

        request_context = {
            'mobile_numbers':
            mobile_numbers,
            'secondary_emails':
            secondary_emails,
            'gpo_email':
            gpo_email,
            'ldap_number':
            ldap_number,
            'roll_number':
            roll_number,
            'user_profile_picture':
            model_field_media_url(user.userprofile.profile_picture),
        }
        request_context.update(forms_context_dict)

        return render(request, 'user_resources/home.html', request_context)
Exemplo n.º 35
0
    def get_url(self, obj, view_name, request, format):
        # Unsaved objects will not have a valid URL.
        if hasattr(obj, 'pk') and obj.pk in (None, ''):
            return None

        # get lookup map (will use properties lookup_map and view)
        lookup_map = self._lookup_map
        get = lambda x: x(obj) if callable(x) else get_attribute(
            obj, x.split('.'))

        # build kwargs for reverse
        try:
            kwargs = dict(
                ((key, get(source)) for (key, source) in lookup_map.items()))
        except (KeyError, AttributeError) as exc:
            raise ValueError(
                "Got {exc_type} when attempting to create url for field "
                "`{field}` on serializer `{serializer}`. "
                "The serializer field lookup_map might be configured incorrectly. "
                "We used `{instance}` instance with lookup map `{lookup_map}`. "
                "Original exception text was: {exc}.".format(
                    exc_type=type(exc).__name__,
                    field=self.field_name,
                    serializer=self.parent.__class__.__name__,
                    instance=obj.__class__.__name__,
                    lookup_map=lookup_map,
                    exc=exc,
                ))

        try:
            return self.reverse(self.view_name,
                                kwargs=kwargs,
                                request=request,
                                format=format)
        except NoReverseMatch as exc:
            raise ImproperlyConfigured(
                "Could not resolve URL for hyperlinked relationship in field "
                "`{field}` on serializer `{serializer}`. "
                "You may have failed to include the related model in your API, "
                "or incorrectly configured `view_name` or `lookup_map` "
                "attribute on this field. Original error: {exc}".format(
                    field=self.field_name,
                    view_name=self.view_name,
                    serializer=self.parent.__class__.__name__,
                    kwargs=kwargs,
                    exc=exc,
                ))
Exemplo n.º 36
0
def _relation_to_json(field, value=None, many=None):
    serializer = field.serializer
    if many is None:
        many = field.many

    name_field_name = serializer.get_name_field()
    name_source = serializer.get_field(
        name_field_name
    ).source or name_field_name
    source_attrs = name_source.split('.')
    value = value or field.value

    if not (
        isinstance(value, list)
        and not isinstance(value, six.string_types)
        and not isinstance(value, UUID)
    ):
        value = [value]

    results = []
    model = serializer.get_model()
    for v in value:
        if v:
            if hasattr(v, 'instance'):
                instance = v.instance
            else:
                if v is None:
                    continue
                else:
                    if isinstance(v, model):
                        instance = v
                    else:
                        instance = model.objects.get(
                            pk=str(v)
                        )
            result = {
                'id': str(instance.pk),
                'name': get_attribute(instance, source_attrs)
            }
            results.append(result)

    if not many:
        # single value result
        results = results[0] if len(results) else None
    return mark_safe(json.dumps(results))
Exemplo n.º 37
0
    def get_url(self, obj, view_name, request, format):
        """ Given an object, return the URL that hyperlinks to the object.

        May raise a `NoReverseMatch` if the `view_name` is not configured
        to correctly match the URL conf.
        """
        # Unsaved objects will not yet have a valid URL.
        if hasattr(obj, 'pk') and obj.pk in (None, ''):
            return None

        kwargs = {}
        for field, kwarg in self.multi_lookup_map.items():
            kwargs[kwarg] = get_attribute(obj, field.split('.'))

        return self.reverse(view_name,
                            kwargs=kwargs,
                            request=request,
                            format=format)
Exemplo n.º 38
0
    def get_attribute(self, obj):
        source = self.source or self.field_name
        try:
            field = fields.get_attribute(obj, source.split('.'))
        except AttributeError:
            field = None

        if not field:
            return None

        requested_language = self.get_requested_language()

        if requested_language:
            single = self.fetch_single_translation(obj, source, field,
                                                   requested_language)
            return list(single.values())[0] if single and self.flat else single
        else:
            return self.fetch_all_translations(obj, source, field)
Exemplo n.º 39
0
    def get_attribute(self, obj):
        source = self.source or self.field_name
        field = fields.get_attribute(obj, source.split('.'))

        if not field:
            return None

        requested_language = None

        request = self.context.get('request', None)
        if request and request.method == 'GET' and 'lang' in request.GET:
            requested_language = request.GET['lang']

        if requested_language:
            return self.fetch_single_translation(obj, source, field,
                                                 requested_language)
        else:
            return self.fetch_all_translations(obj, source, field)
Exemplo n.º 40
0
    def get_attribute(self, instance):
        if hasattr(instance, 'pk') and instance.pk is None:
            return []

        attr = self.source_attrs[-1]

        # `gc` 是 `GroupConcat` 的缩写
        gc_attr = f'gc_{attr}'
        if hasattr(instance, gc_attr):
            gc_value = getattr(instance, gc_attr)
            if isinstance(gc_value, str):
                return [UUID(pk) for pk in set(gc_value.split(','))]
            else:
                return ''

        relationship = get_attribute(instance, self.source_attrs)
        return relationship.all() if hasattr(relationship,
                                             'all') else relationship
Exemplo n.º 41
0
    def get_serializer_class(self, instance=None, data=empty):
        """
        Returns the appropriate serializer to use for given data or instance.
        """
        if instance is not None:
            for cls, (name, serializer) in self._declared_classes.items():
                if cls == instance.__class__:
                    return serializer
        elif data is not empty:
            try:
                type_value = get_attribute(data, [self.type_field])
            except KeyError:
                raise ValidationError('No type specified.')

            for name, (cls, serializer) in self._declared_types.items():
                if name == type_value:
                    return serializer
        return
Exemplo n.º 42
0
def zip_instance_extra_with_iterable(instance, iterable, extra):
    extra_attrs = dict(
        (key, get_attribute(instance, attrs.split('.')))
        for key, attrs in extra.items()
    )
    return (AttributeProxy(item, **extra_attrs) for item in iterable)
Exemplo n.º 43
0
 def get_iterable(self, instance, source):
     relationship = get_attribute(instance, [source])
     return relationship.all() if (hasattr(relationship, 'all')) else relationship
Exemplo n.º 44
0
 def get_url(self, obj, view_name, request, format):
     url_kwargs = {
         self.parent_lookup_url_kwarg: get_attribute(obj, self.parent_lookup_field.replace('__', '.').split('.')),
         self.lookup_url_kwarg: get_attribute(obj, self.lookup_field.replace('__', '.').split('.')),
     }
     return self.reverse(view_name, kwargs=url_kwargs, request=request, format=format)
Exemplo n.º 45
0
 def get_attribute(self, instance):
     if instance.is_tax_known:
         return super(TaxIncludedDecimalField, self).get_attribute(instance)
     if self.excl_tax_field:
         return get_attribute(instance, (self.excl_tax_field, ))
     return self.excl_tax_value
Exemplo n.º 46
0
 def get_attribute(self, instance):
     return get_attribute(instance, self.source_attrs)
Exemplo n.º 47
0
 def get_attribute(self, instance):
     relationship = get_attribute(instance, self.source_attrs)
     return relationship.all() if (hasattr(relationship, 'all')) else relationship
    def extract_included(fields, resource, resource_instance, included_resources):
        # this function may be called with an empty record (example: Browsable Interface)
        if not resource_instance:
            return

        included_data = list()
        current_serializer = fields.serializer
        context = current_serializer.context
        include_config = utils.get_included_configuration(current_serializer)
        included_resources = copy.copy(included_resources)

        for field_name, field in six.iteritems(fields):
            # Skip URL field
            if field_name == api_settings.URL_FIELD_NAME:
                continue

            # Skip fields without relations or serialized data
            if not isinstance(field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer)):
                continue

            # Skip disabled fields
            if include_config[field_name] == False:
                continue

            try:
                included_resources.remove(field_name)
            except ValueError:
                # Skip fields not in requested included resources
                continue

            try:
                relation_instance_or_manager = get_attribute(resource_instance, field.source.split('.'))
            except AttributeError:
                try:
                    # For ManyRelatedFields if `related_name` is not set we need to access `foo_set` from `source`
                    relation_instance_or_manager = get_attribute(resource_instance, field.child_relation.source.split('.'))
                except AttributeError:
                    if not hasattr(current_serializer, field.source):
                        continue
                    serializer_method = get_attribute(current_serializer, field.source.split('.'))
                    relation_instance_or_manager = serializer_method(resource_instance)

            new_included_resources = [key.replace('%s.' % field_name, '', 1)
                                      for key in included_resources
                                      if field_name == key.split('.')[0]]
            serializer_data = resource.get(field_name)

            serializer_instances = []

            if isinstance(field, relations.ManyRelatedField):
                # # serializer_class = include_config.get(field_name)
                # serializer_class = utils.get_serializer_from_instance_and_serializer()
                # serializer_instance = serializer_class(relation_instance_or_manager.all(), many=True, context=context)

                if isinstance(current_serializer.instance, Iterable):
                    iterable = []
                    for obj in current_serializer.instance:
                        iterable += field.get_attribute(obj)
                else:
                    iterable = field.get_attribute(current_serializer.instance)

                for item in iterable:
                    serializer_class = utils.get_serializer_from_instance_and_serializer(item,
                                                                                         current_serializer,
                                                                                         field_name)
                    serializer_instance = serializer_class(item, context=context)
                    serializer_instances.append(serializer_instance)

            if isinstance(field, relations.RelatedField):
                # serializer_class = include_config.get(field_name)
                if relation_instance_or_manager is None:
                    continue

                serializer_class = utils.get_serializer_from_instance_and_serializer(relation_instance_or_manager, current_serializer, field_name)
                serializer_instance = serializer_class(relation_instance_or_manager, context=context)
                serializer_instances.append(serializer_instance)

            for serializer_instance in serializer_instances:

                serializer_data = serializer_instance.data

                relation_type = utils.get_resource_type_from_serializer(serializer_instance.__class__)

                # Get the serializer fields
                serializer_fields = utils.get_serializer_fields(serializer_instance)
                if serializer_data:
                    included_data.append(
                            JSONRenderer.build_json_resource_obj(
                                    serializer_fields, serializer_data,
                                    serializer_instance.instance, relation_type)
                    )
                    included_data.extend(
                            JSONRenderer.extract_included(
                                    serializer_fields, serializer_data, serializer_instance.instance, new_included_resources
                            )
                    )

        return utils.format_keys(included_data)
    def extract_relationships(fields, resource, resource_instance):
        # Avoid circular deps
        from rest_framework_json_api.relations import ResourceRelatedField

        data = OrderedDict()

        # Don't try to extract relationships from a non-existent resource
        if resource_instance is None:
            return

        for field_name, field in six.iteritems(fields):
            # Skip URL field
            if field_name == api_settings.URL_FIELD_NAME:
                continue

            # Skip fields without relations
            if not isinstance(field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer)):
                continue

            source = field.source
            try:
                relation_instance_or_manager = get_attribute(resource_instance, source.split('.'))
            except AttributeError:
                # if the field is not defined on the model then we check the serializer
                # and if no value is there we skip over the field completely
                serializer_method = getattr(field.parent, source, None)
                if serializer_method and hasattr(serializer_method, '__call__'):
                    relation_instance_or_manager = serializer_method(resource_instance)
                else:
                    continue

            # relation_type = utils.get_related_resource_type(field)

            if isinstance(field, relations.HyperlinkedIdentityField):
                relation_type = utils.get_related_resource_type(field)
                # special case for HyperlinkedIdentityField
                relation_data = list()

                # Don't try to query an empty relation
                relation_queryset = relation_instance_or_manager.all() \
                    if relation_instance_or_manager is not None else list()

                for related_object in relation_queryset:
                    relation_data.append(
                            OrderedDict([('type', relation_type), ('id', encoding.force_text(related_object.pk))])
                    )

                data.update({field_name: {
                    'links': {
                        "related": resource.get(field_name)},
                    'data': relation_data,
                    'meta': {
                        'count': len(relation_data)
                    }
                }})
                continue

            if isinstance(field, ResourceRelatedField):
                # special case for ResourceRelatedField
                relation_data = {
                    'data': resource.get(field_name)
                }

                field_links = field.get_links(resource_instance)
                relation_data.update(
                        {'links': field_links}
                        if field_links else dict()
                )
                data.update({field_name: relation_data})
                continue

            if isinstance(field, (relations.PrimaryKeyRelatedField, relations.HyperlinkedRelatedField)):
                relation_id = relation_instance_or_manager.pk if resource.get(field_name) else None
                relation_type = utils.get_related_resource_type(field)

                relation_data = {
                    'data': (
                        OrderedDict([('type', relation_type), ('id', encoding.force_text(relation_id))])
                        if relation_id is not None else None)
                }

                relation_data.update(
                        {'links': {'related': resource.get(field_name)}}
                        if isinstance(field, relations.HyperlinkedRelatedField) and resource.get(field_name) else dict()
                )
                data.update({field_name: relation_data})
                continue

            if isinstance(field, relations.ManyRelatedField):

                if isinstance(field.child_relation, ResourceRelatedField):
                    # special case for ResourceRelatedField

                    if field_name not in resource:
                        continue


                    relation_data = {
                        'data': resource.get(field_name)
                    }

                    field_links = field.child_relation.get_links(resource_instance)
                    relation_data.update(
                            {'links': field_links}
                            if field_links else dict()
                    )
                    relation_data.update(
                            {
                                'meta': {
                                    'count': len(resource.get(field_name))
                                }
                            }
                    )
                    data.update({field_name: relation_data})
                    continue

                relation_data = list()
                for related_object in relation_instance_or_manager.all():
                    related_object_type = utils.get_instance_or_manager_resource_type(related_object)
                    relation_data.append(OrderedDict([
                        ('type', related_object_type),
                        ('id', encoding.force_text(related_object.pk))
                    ]))
                data.update({
                    field_name: {
                        'data': relation_data,
                        'meta': {
                            'count': len(relation_data)
                        }
                    }
                })
                continue

            if isinstance(field, ListSerializer):
                relation_data = list()

                serializer_data = resource.get(field_name)
                resource_instance_queryset = list(relation_instance_or_manager.all())
                if isinstance(serializer_data, list):
                    for position in range(len(serializer_data)):
                        nested_resource_instance = resource_instance_queryset[position]
                        nested_resource_instance_type = utils.get_resource_type_from_serializer(field.child)
                        relation_data.append(OrderedDict([
                            ('type', nested_resource_instance_type),
                            ('id', encoding.force_text(nested_resource_instance.pk))
                        ]))

                    data.update({field_name: {'data': relation_data}})
                    continue

            if isinstance(field, ModelSerializer):
                data.update({
                    field_name: {
                        'data': (
                            OrderedDict([
                                ('type', relation_type),
                                ('id', encoding.force_text(relation_instance_or_manager.pk))
                            ]) if resource.get(field_name) else None)
                    }
                })
                continue

        return utils.format_keys(data)