예제 #1
0
파일: resources.py 프로젝트: mkasie/selena
    def dehydrate(self, bundle, for_list=True):
        if not bundle.obj or not bundle.obj.pk:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' does not have a primary key and can not "
                    "be used in a ToMany context." % bundle.obj, )
            return []
        the_m2ms = None
        if isinstance(self.attribute, basestring):
            the_m2ms = getattr(bundle.obj, self.attribute)
        elif callable(self.attribute):
            the_m2ms = self.attribute(bundle)
        if not the_m2ms:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' has an empty attribute '%s' and doesn't "
                    "allow a null value." % (bundle.obj, self.attribute), )
            return []
        self.m2m_resources = []
        m2m_dehydrated = []
        for m2m in the_m2ms.filter(*self.filter_args_func(),
                                   **self.filter_kwargs_func()):
            m2m_resource = self.get_related_resource(m2m)
            m2m_bundle = Bundle(obj=m2m, request=bundle.request)
            self.m2m_resources.append(m2m_resource)
            m2m_dehydrated.append(
                self.dehydrate_related(m2m_bundle, m2m_resource, for_list), )

        return m2m_dehydrated
예제 #2
0
 def build_related_resource(self, value):
     """
     Used to ``hydrate`` the data provided. If just a URL is provided,
     the related resource is attempted to be loaded. If a
     dictionary-like structure is provided, a fresh resource is
     created.
     """
     self.fk_resource = self.to_class()
     
     if isinstance(value, basestring):
         # We got a URI. Load the object and assign it.
         try:
             obj = self.fk_resource.get_via_uri(value)
             return self.fk_resource.full_dehydrate(obj)
         except ObjectDoesNotExist:
             raise ApiFieldError("Could not find the provided object via resource URI '%s'." % value)
     elif hasattr(value, 'items'):
         # Try to hydrate the data provided.
         value = dict_strip_unicode_keys(value)
         self.fk_bundle = Bundle(data=value)
         try:
             return self.fk_resource.obj_update(self.fk_bundle, **value)
         except NotFound:
             try:
                 # Attempt lookup by primary key
                 lookup_kwargs = dict((k, v) for k, v in value.iteritems() if getattr(self.fk_resource, k).unique)
                 if not lookup_kwargs:
                     raise NotFound
                 return self.fk_resource.obj_update(self.fk_bundle, **lookup_kwargs)
             except NotFound:
                 return self.fk_resource.full_hydrate(self.fk_bundle)
         except MultipleObjectsReturned:
             return self.fk_resource.full_hydrate(self.fk_bundle)
     else:
         raise ApiFieldError("The '%s' field has was given data that was not a URI and not a dictionary-alike: %s." % (self.instance_name, value))
예제 #3
0
파일: __init__.py 프로젝트: ekr/ietfdb
    def dehydrate(self, bundle, for_list=True):
        foreign_obj = None
        
        if callable(self.attribute):
            previous_obj = bundle.obj
            foreign_obj = self.attribute(bundle)
        elif isinstance(self.attribute, six.string_types):
            foreign_obj = bundle.obj

            for attr in self._attrs:
                previous_obj = foreign_obj
                try:
                    foreign_obj = getattr(foreign_obj, attr, None)
                except ObjectDoesNotExist:
                    foreign_obj = None

        if not foreign_obj:
            if not self.null:
                if callable(self.attribute):
                    raise ApiFieldError(u"The related resource for resource %s could not be found." % (previous_obj))
                else:
                    raise ApiFieldError(u"The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr))
            return None

        fk_resource = self.get_related_resource(foreign_obj)

        # Up to this point we've copied the code from tastypie 0.13.1.  Now
        # we add caching.
        cache_key = fk_resource.generate_cache_key('related', pk=foreign_obj.pk, for_list=for_list, )
        dehydrated = fk_resource._meta.cache.get(cache_key)
        if dehydrated is None:
            fk_bundle = Bundle(obj=foreign_obj, request=bundle.request)
            dehydrated = self.dehydrate_related(fk_bundle, fk_resource, for_list=for_list)
            fk_resource._meta.cache.set(cache_key, dehydrated)
        return dehydrated
예제 #4
0
    def dehydrate(self, bundle, for_list=True):
        foreign_obj = None

        if callable(self.attribute):
            previous_obj = bundle.obj
            foreign_obj = self.attribute(bundle)
        elif isinstance(self.attribute, six.string_types):
            foreign_obj = bundle.obj

            for attr in self._attrs:
                previous_obj = foreign_obj
                try:
                    foreign_obj = getattr(foreign_obj, attr, None)
                except ObjectDoesNotExist:
                    foreign_obj = None

        if not foreign_obj:
            if not self.null:
                if callable(self.attribute):
                    raise ApiFieldError("The related resource for resource %s could not be found." % (previous_obj))
                else:
                    raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr))
            return None

        fk_resource = self.get_related_resource(foreign_obj)
        fk_bundle = Bundle(obj=foreign_obj, request=bundle.request)
        return self.dehydrate_related(fk_bundle, fk_resource, for_list=for_list)
예제 #5
0
 def dehydrate(self, bundle):
     if not bundle.obj or not bundle.obj.pk:
         if not self.null:
             raise ApiFieldError("The model '%r' does not have a primary key and can not be used in a ToMany context." % bundle.obj)
         
         return []
     
     if not getattr(bundle.obj, self.attribute):
         if not self.null:
             raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (bundle.obj, self.attribute))
         
         return []
     
     self.m2m_resources = []
     m2m_dehydrated = []
     
     # TODO: Also model-specific and leaky. Relies on there being a
     #       ``Manager`` there.
     for m2m in getattr(bundle.obj, self.attribute).all():
         m2m_resource = self.get_related_resource(m2m)
         m2m_bundle = Bundle(obj=m2m)
         self.m2m_resources.append(m2m_resource)
         m2m_dehydrated.append(self.dehydrate_related(m2m_bundle, m2m_resource))
     
     return m2m_dehydrated
예제 #6
0
    def resource_from_uri(self,
                          fk_resource,
                          uri,
                          request=None,
                          related_obj=None,
                          related_name=None):
        """
        Given a URI is provided, the related resource is attempted to be
        loaded based on the identifiers in the URI.
        """
        err_msg = "Could not find the provided %s object via resource URI '%s'." % (
            fk_resource._meta.resource_name,
            uri,
        )

        if not uri:
            raise ApiFieldError(err_msg)

        try:
            obj = fk_resource.get_via_uri(uri, request=request)
            bundle = fk_resource.build_bundle(obj=obj,
                                              request=request,
                                              via_uri=True)
            return fk_resource.full_dehydrate(bundle)
        except ObjectDoesNotExist:
            raise ApiFieldError(err_msg)
예제 #7
0
파일: api.py 프로젝트: oaubert/mediathread
    def dehydrate(self, bundle):
        if not bundle.obj or not bundle.obj.pk:
            if not self.null:
                raise ApiFieldError("The model '%r' does not have a primary \
                    key and can not be used in a ToMany context." % bundle.obj)

            return []

        the_m2ms = None
        previous_obj = bundle.obj
        attr = self.attribute

        if isinstance(self.attribute, basestring):
            attrs = self.attribute.split('__')
            the_m2ms = bundle.obj

            for attr in attrs:
                previous_obj = the_m2ms
                try:
                    the_m2ms = getattr(the_m2ms, attr, None)
                    the_m2ms = self.apply_m2m_filters(bundle.request,
                                                      attr,
                                                      the_m2ms.all())
                except ObjectDoesNotExist:
                    the_m2ms = None

                if not the_m2ms:
                    break

                try:
                    the_m2ms = self.apply_sorting(bundle.request,
                                                  the_m2ms.all())
                except InvalidSortError:
                    pass

        elif callable(self.attribute):
            the_m2ms = self.attribute(bundle)

        if not the_m2ms:
            if not self.null:
                raise ApiFieldError("The model '%r' has an empty attribute \
                                    '%s' and doesn't allow a null value."
                                    % (previous_obj, attr))

            return []

        self.m2m_resources = []
        m2m_dehydrated = []

        # TODO: Also model-specific and leaky. Relies on there being a
        #       ``Manager`` there.
        for m2m in the_m2ms.select_related():
            m2m_resource = self.get_related_resource(m2m)
            m2m_bundle = Bundle(obj=m2m, request=bundle.request)
            self.m2m_resources.append(m2m_resource)
            m2m_dehydrated.append(self.dehydrate_related(m2m_bundle,
                                                         m2m_resource))

        return m2m_dehydrated
예제 #8
0
    def dehydrate(self, bundle, for_list=True):
        if not bundle.obj or not bundle.obj.pk:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' does not have a primary key and can not be used in a ToMany context."
                    % bundle.obj)

            return []

        the_m2ms = None
        previous_obj = bundle.obj
        attr = self.attribute

        if isinstance(self.attribute, six.string_types):
            attrs = self.attribute.split('__')
            the_m2ms = bundle.obj

            for attr in attrs:
                previous_obj = the_m2ms
                try:
                    the_m2ms = getattr(the_m2ms, attr, None)
                except ObjectDoesNotExist:
                    the_m2ms = None

                if not the_m2ms:
                    break

        elif callable(self.attribute):
            the_m2ms = self.attribute(bundle)

        if not the_m2ms:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' has an empty attribute '%s' and doesn't allow a null value."
                    % (previous_obj, attr))

            return []

        self.m2m_resources = []
        m2m_dehydrated = []

        # TODO: Also model-specific and leaky. Relies on there being a
        # ``Manager`` there.
        the_m2ms_list = the_m2ms.all()
        if self.filter:
            the_m2ms_list = the_m2ms_list.filter(**filter)
        if self.limit:
            the_m2ms_list = the_m2ms_list[0:self.limit]

        for m2m in the_m2ms_list:
            m2m_resource = self.get_related_resource(m2m)
            m2m_bundle = Bundle(obj=m2m, request=bundle.request)
            self.m2m_resources.append(m2m_resource)
            m2m_dehydrated.append(
                self.dehydrate_related(m2m_bundle,
                                       m2m_resource,
                                       for_list=for_list))

        return m2m_dehydrated
예제 #9
0
    def hydrate(self, bundle):
        """
        Takes data stored in the bundle for the field and returns it. Used for
        taking simple data and building a instance object.
        """
        if self.readonly:
            return None
        if not bundle.data.has_key(self.instance_name):

            is_related = getattr(self, 'is_related', False)
            is_m2m = getattr(self, 'is_m2m', False)

            if is_related and not is_m2m:
                # We've got an FK (or alike field) & a possible parent object.
                # Check for it.
                if bundle.related_obj and bundle.related_name in (
                        self.attribute, self.instance_name):
                    return bundle.related_obj

            # Functor for safely checking if bundle.obj has a non-None property
            def has_non_null_attr(obj, name):
                try:
                    return getattr(obj, name, None) is not None
                except:
                    if is_related:
                        return None
                    else:
                        raise

            if self.blank:
                return None
            elif self.attribute and has_non_null_attr(bundle.obj,
                                                      self.attribute):
                return getattr(bundle.obj, self.attribute)
            elif self.instance_name and has_non_null_attr(
                    bundle.obj, self.instance_name):
                return getattr(bundle.obj, self.instance_name)
            elif self.has_default():
                if callable(self._default):
                    return self._default()

                return self._default
            elif self.null:
                return None
            else:
                raise ApiFieldError(
                    "The '%s' field has no data and doesn't allow a default or null value."
                    % self.instance_name)

        bundle_val = bundle.data[self.instance_name]

        if bundle_val is None and not self.null:
            raise ApiFieldError("The '%s' field doesn't allow a null value." %
                                self.instance_name)
        else:
            return bundle_val
예제 #10
0
    def hydrate_recipient(self, bundle):
        recipient = bundle.data['recipient']
        try:
            if bundle.request.user.username == recipient:
                raise ApiFieldError("不能邀请自己")

            user = User.objects.get_by_natural_key(recipient)
            bundle.data['recipient'] = user
        except ObjectDoesNotExist:
            raise ApiFieldError("用户不存在")
        return bundle
예제 #11
0
    def hydrate_license(self, bundle):
        if "license" not in bundle.data:
            raise ApiFieldError("You must set a license for your picture")

        try:
            license = License.objects.get(id=bundle.data["license"])
        except:
            raise ApiFieldError("The selected license is incorrect")

        bundle.obj.license = license
        return bundle
예제 #12
0
    def hydrate(self, bundle):
        value = super(DateTimeField, self).hydrate(bundle)

        if value and not hasattr(value, 'year'):
            if isinstance(value, six.string_types):
                try:
                    # Try to rip a date/datetime out of it.
                    value = make_aware(parse(value))
                except (ValueError, TypeError):
                    raise ApiFieldError("Datetime provided to '%s' field doesn't appear to be a valid datetime string: '%s'" % (self.instance_name, value))

            else:
                raise ApiFieldError("Datetime provided to '%s' field must be a string: %s" % (self.instance_name, value))

        return value
예제 #13
0
    def dehydrate(self, bundle, **kwargs):
        """
            This modified field, allow to include resource_uri of related
            resources without doing another database query.

            Using select_related() in resource.meta.queryset also avoids
            doing extra queries for each object, can be used instead
            of this class
        """
        if not self.full:
            pk = getattr(bundle.obj, self.attribute + "_id", None)
            if not pk:
                if not self.null:
                    raise ApiFieldError(
                        """The model '%r' has an empty attribute '%s'
                        and doesn't allow a null value.""" %
                        (bundle.obj, self.attribute))
                return None
            # just create a temporal object with only PK
            temporal_class = type('TemporalModel', (object,), {'pk': pk})
            temporal_obj = temporal_class()

            # from this point, is almost the same stuff that tastypie does.
            self.fk_resource = self.get_related_resource(temporal_obj)
            fk_bundle = Bundle(
                obj=temporal_obj, request=bundle.request)
            return self.dehydrate_related(fk_bundle, self.fk_resource)

        return super(OptimizedToOneField, self).dehydrate(bundle, **kwargs)
예제 #14
0
 def to_time(self, s):
     try:
         dt = parse(s)
     except (ValueError, TypeError) as e:
         raise ApiFieldError(str(e))
     else:
         return datetime.time(dt.hour, dt.minute, dt.second, dt.microsecond)
예제 #15
0
    def dehydrate(self, bundle, **kwargs):
        """
        If field is configured to only return the resource URI (full=False),
        a temporal object will be created with only the PK available,
        this key will be filled with the value saved at self.attribute_id

        In case, field's self.full is set to True, original dehydrate process
        will be used.

        """
        if not self.full:
            pk = getattr(bundle.obj, self.attribute + "_id", None)
            if not pk:
                if not self.null:
                    raise ApiFieldError(
                        """The model '%r' has an empty attribute '%s'
                        and doesn't allow a null value.""" %
                        (bundle.obj, self.attribute))
                return None
            # just create a temporal object with only PK
            temporal_obj = type('TemporalModel', (object,), {'pk': pk})()

            # from this point, is almost the same stuff that tastypie does.
            self.fk_resource = self.get_related_resource(temporal_obj)
            fk_bundle = Bundle(
                obj=temporal_obj, request=bundle.request)
            return self.dehydrate_related(fk_bundle, self.fk_resource)

        return super(OptimizedToOneField, self).dehydrate(bundle, **kwargs)
    def __init__(self, *args, **kwargs):
        super(ChildResource, self).__init__(*args, **kwargs)

        # Set the parent resource and name
        self.parent_field_name = self._meta.parent
        self.parent_resource = None
        for field, field_type in self.fields.iteritems():
            if field == self.parent_field_name and isinstance(
                    field_type, RelatedField):
                self.parent_resource = field_type.to
        if self.parent_resource is None:
            raise ApiFieldError("Could not find parent resource: %s" %
                                self._meta.parent)
        self.parent_resource_instance = self.parent_resource(
        )  # cache an instance of the parent resource

        # Add filtering for the parent
        filters_for_parent = self._meta.filtering.setdefault(
            self.parent_field_name, [])
        if filters_for_parent not in (
                ALL, ALL_WITH_RELATIONS) and "exact" not in filters_for_parent:
            if isinstance(filters_for_parent, list):
                filters_for_parent.append("exact")
            elif isinstance(filters_for_parent, tuple):
                filters_for_parent = list(filters_for_parent)
                filters_for_parent.append("exact")
                self._meta.filtering[self.parent_field_name] = tuple(
                    filters_for_parent)
예제 #17
0
 def resource_from_uri(self, fk_resource, uri, request=None, related_obj=None, related_name=None):
     try:
         obj = fk_resource.get_via_uri(uri, request=request)
         fk_resource = self.get_related_resource(obj)
         return super(GenericForeignKeyField, self).resource_from_uri(fk_resource, uri, request, related_obj, related_name)
     except ObjectDoesNotExist:
         raise ApiFieldError("Could not find the provided object via resource URI '%s'." % uri)
예제 #18
0
    def hydrate_m2m(self, bundle):
        if self.readonly:
            return None

        if bundle.data.get(self.instance_name) is None:
            if self.blank:
                return []
            if self.null:
                return []
            raise ApiFieldError(
                "The '%s' field has no data and doesn't allow a null value." %
                self.instance_name)

        kwargs = {
            'request': bundle.request,
        }

        if self.related_name:
            kwargs['related_obj'] = bundle.obj
            kwargs['related_name'] = self.related_name

        return [
            self.build_related_resource(value, **kwargs)
            for value in bundle.data.get(self.instance_name)
            if value is not None
        ]
예제 #19
0
    def dehydrate(self, bundle, for_list=True):
        the_m2ms = None

        if isinstance(self.attribute, basestring):
            the_m2ms = getattr(bundle.obj, self.attribute)
        elif callable(self.attribute):
            the_m2ms = self.attribute(bundle)

        if not the_m2ms:
            if not self.null:
                raise ApiFieldError(
                    "The document %r has an empty attribute '%s' and does not allow a null value."
                    % (bundle.obj, self.attribute))
            return {}

        self.m2m_resources = {}
        m2m_dehydrated = {}

        # the_m2ms is a list, not a queryset
        for m2m_key, m2m_obj in the_m2ms.iteritems():
            m2m_resource = self.get_related_resource(m2m_obj)
            m2m_bundle = tastypie_bundle.Bundle(obj=m2m_obj,
                                                request=bundle.request)
            self.m2m_resources[m2m_key] = m2m_resource
            m2m_dehydrated[m2m_key] = self.dehydrate_related(m2m_bundle,
                                                             m2m_resource,
                                                             for_list=for_list)
        return m2m_dehydrated
예제 #20
0
    def hydrate(self, bundle):
        """
        Takes data stored in the bundle for the field and returns it. Used for
        taking simple data and building a instance object.
        """
        if self.readonly:
            return None

        if not bundle.data.has_key(self.instance_name):
            if self.attribute and getattr(bundle.obj, self.attribute, None):
                return getattr(bundle.obj, self.attribute)
            elif self.instance_name and hasattr(bundle.obj,
                                                self.instance_name):
                return getattr(bundle.obj, self.instance_name)
            elif self.has_default():
                if callable(self._default):
                    return self._default()

                return self._default
            elif self.null:
                return None
            else:
                raise ApiFieldError(
                    "The '%s' field has no data and doesn't allow a default or null value."
                    % self.instance_name)

        return bundle.data[self.instance_name]
예제 #21
0
    def hydrate_m2m(self, bundle):
        if self.readonly:
            return None

        if bundle.data.get(self.instance_name) is None:
            if self.blank:
                return []
            elif self.null:
                return []
            else:
                raise ApiFieldError(
                    "The '%s' field has no data and doesn't allow a null value."
                    % self.instance_name)

        m2m_hydrated = []

        for value in bundle.data.get(self.instance_name):
            if value is None:
                continue

            kwargs = {
                'request': bundle.request,
            }

            if self.related_name:
                kwargs['related_obj'] = bundle.obj
                kwargs['related_name'] = self.related_name

            m2m_hydrated.append(self.build_related_resource(value, **kwargs))

        return m2m_hydrated
예제 #22
0
    def hydrate(self, bundle):
        """
        Takes data stored in the bundle for the field and returns it. Used for
        taking simple data and building a instance object.
        """
        if self.readonly:
            return None
        if not bundle.data.has_key(self.instance_name):
            if getattr(self, 'is_related',
                       False) and not getattr(self, 'is_m2m', False):
                # We've got an FK (or alike field) & a possible parent object.
                # Check for it.
                if bundle.related_obj and bundle.related_name in (
                        self.attribute, self.instance_name):
                    return bundle.related_obj
            if self.blank:
                return None
            elif self.attribute and getattr(bundle.obj, self.attribute, None):
                return getattr(bundle.obj, self.attribute)
            elif self.instance_name and hasattr(bundle.obj,
                                                self.instance_name):
                return getattr(bundle.obj, self.instance_name)
            elif self.has_default():
                if callable(self._default):
                    return self._default()

                return self._default
            elif self.null:
                return None
            else:
                raise ApiFieldError(
                    "The '%s' field has no data and doesn't allow a default or null value."
                    % self.instance_name)

        return bundle.data[self.instance_name]
예제 #23
0
    def dehydrate(self, bundle, for_list=True):
        """
        Takes data from the provided object and prepares it for the
        resource.
        """
        if self.attribute is not None:
            current_object = bundle.obj

            for attr in self._attrs:
                previous_object = current_object
                current_object = getattr(current_object, attr, None)

                if current_object is None:
                    if self.has_default():
                        current_object = self._default
                        # Fall out of the loop, given any further attempts at
                        # accesses will fail miserably.
                        break
                    elif self.null:
                        current_object = None
                        # Fall out of the loop, given any further attempts at
                        # accesses will fail miserably.
                        break
                    else:
                        raise ApiFieldError("The object '%r' has an empty attribute '%s' and doesn't allow a default or null value." % (previous_object, attr))

            if callable(current_object):
                current_object = current_object()

            return self.convert(current_object)

        if self.has_default():
            return self.convert(self.default)
        else:
            return None
예제 #24
0
    def dehydrate(self, bundle):
        foreign_obj = None
        depth = getattr(bundle, 'depth', 0)

        if isinstance(self.attribute, basestring):
            attrs = self.attribute.split('__')
            foreign_obj = bundle.obj

            for attr in attrs:
                previous_obj = foreign_obj
                try:
                    foreign_obj = getattr(foreign_obj, attr, None)
                except ObjectDoesNotExist:
                    foreign_obj = None
        elif callable(self.attribute):
            foreign_obj = self.attribute(bundle)

        if not foreign_obj:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' has an empty attribute '%s' and doesn't allow a null value."
                    % (previous_obj, attr))

            return None

        self.fk_resource = self.get_related_resource(foreign_obj)
        fk_bundle = Bundle(obj=foreign_obj, request=bundle.request)
        fk_bundle.depth = depth + 1
        return self.dehydrate_related(fk_bundle, self.fk_resource)
예제 #25
0
    def build_related_resource(self,
                               value,
                               request=None,
                               related_obj=None,
                               related_name=None):
        """
        Returns a bundle of data built by the related resource, usually via
        ``hydrate`` with the data provided.

        Accepts either a URI, a data dictionary (or dictionary-like structure)
        or an object with a ``pk``.
        """
        self.fk_resource = self.to_class()
        kwargs = {
            'request': request,
            'related_obj': related_obj,
            'related_name': related_name,
        }

        if isinstance(value, basestring):
            # We got a URI. Load the object and assign it.
            return self.resource_from_uri(self.fk_resource, value, **kwargs)
        elif hasattr(value, 'items'):
            # We've got a data dictionary.
            # Since this leads to creation, this is the only one of these
            # methods that might care about "parent" data.
            return self.resource_from_data(self.fk_resource, value, **kwargs)
        elif hasattr(value, 'pk'):
            # We've got an object with a primary key.
            return self.resource_from_pk(self.fk_resource, value, **kwargs)
        else:
            raise ApiFieldError(
                "The '%s' field has was given data that was not a URI, not a dictionary-alike and does not have a 'pk' attribute: %s."
                % (self.instance_name, value))
예제 #26
0
    def dehydrate(self, bundle, for_list=True):
        if not bundle.obj or not bundle.obj.pk:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' does not have a primary key and can not be used in a ToMany context."
                    % bundle.obj)

            return []

        the_m2ms = None
        previous_obj = bundle.obj
        attr = self.attribute

        if callable(self.attribute):
            the_m2ms = self.attribute(bundle)
        elif isinstance(self.attribute, six.string_types):
            the_m2ms = bundle.obj

            for attr in self._attrs:
                previous_obj = the_m2ms
                try:
                    the_m2ms = getattr(the_m2ms, attr, None)
                except ObjectDoesNotExist:
                    the_m2ms = None

                if not the_m2ms:
                    break

        if not the_m2ms:
            if not self.null:
                raise ApiFieldError(
                    "The model '%r' has an empty attribute '%s' and doesn't allow a null value."
                    % (previous_obj, attr))

            return []

        if isinstance(the_m2ms, models.Manager):
            the_m2ms = the_m2ms.all()

        m2m_dehydrated = [
            self.dehydrate_related(Bundle(obj=m2m, request=bundle.request),
                                   self.get_related_resource(m2m),
                                   for_list=for_list) for m2m in the_m2ms
        ]

        return m2m_dehydrated
예제 #27
0
 def hydrate(self, bundle):
     if bundle.data.get(self.instance_name) is None:
         if self.null:
             return None
         else:
             raise ApiFieldError("The '%s' field has no data and doesn't allow a null value." % self.instance_name)
     
     return self.build_related_resource(bundle.data.get(self.instance_name))
예제 #28
0
    def hydrate_project(self, bundle):
        if "project" not in bundle.data or "slug" not in bundle.data[
                "project"] or "lang" not in bundle.data["project"]:
            raise ApiFieldError("A picture must be attached to a project")

        project = bundle.data["project"]
        try:
            project = I4pProjectTranslation.objects.get(
                slug=project["slug"],
                language_code=project["lang"],
                master__in=I4pProject.on_site.all())
        except:
            raise ApiFieldError("Unable to find associated project")

        project = project.master
        bundle.obj.project = project
        return bundle
예제 #29
0
    def save(self, bundle, skip_errors=False):
        obj = self.content_object.hydrate(bundle).obj
        if Invite.objects.filter(
                recipient=self.recipient.hydrate(bundle).obj,
                content_type=ContentType.objects.get_for_model(obj),
                object_id=obj.id).exists():
            raise ApiFieldError("用户邀请")

        return super(InviteResource, self).save(bundle, skip_errors)
예제 #30
0
    def resource_from_data(self,
                           fk_resource,
                           data,
                           request=None,
                           related_obj=None,
                           related_name=None):
        """
        Given a dictionary-like structure is provided, a fresh related
        resource is created using that data.
        """
        # Try to hydrate the data provided.
        data = dict_strip_unicode_keys(data)
        fk_bundle = fk_resource.build_bundle(data=data, request=request)

        if related_obj:
            fk_bundle.related_obj = related_obj
            fk_bundle.related_name = related_name

        # We need to check to see if updates are allowed on the FK
        # resource. If not, we'll just return a populated bundle instead
        # of mistakenly updating something that should be read-only.
        if not fk_resource.can_update():

            # If the resource already exists and the client specified where to find it, we look it up.
            if 'resource_uri' in data:
                obj = fk_resource.get_via_uri(data['resource_uri'],
                                              request=request)
                fk_bundle.install_existing_obj(obj)
                return fk_bundle

            # If the resource supports creation, then we can full_hydrate() and create a new instance.
            elif fk_resource.can_create():
                return fk_resource.full_hydrate(fk_bundle)

            else:
                raise ApiFieldError(
                    "Resource %s does not support being created via POST" %
                    fk_resource._meta.resource_name)

        try:
            return fk_resource.obj_update(fk_bundle, **data)
        except NotFound:
            try:
                # Attempt lookup by primary key
                lookup_kwargs = dict((k, v) for k, v in data.iteritems()
                                     if getattr(fk_resource, k).unique)

                if not lookup_kwargs:
                    raise NotFound()
                return fk_resource.obj_update(fk_bundle, **lookup_kwargs)
            except NotFound:
                fk_bundle = fk_resource.full_hydrate(fk_bundle)
                fk_resource.is_valid(fk_bundle, request)
                return fk_bundle
        except MultipleObjectsReturned:
            return fk_resource.full_hydrate(fk_bundle)