예제 #1
0
    def post_zip(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        self.is_authenticated(request)
        self.throttle_check(request)

        try:
            event_obj = Event.objects.get(pk=kwargs['pk'])
            cont = rackspace.cloud_files.get_container(
                event_obj.container_name)
            album_zip = cont.get_object('{}.zip'.format(event_obj.uuid))

            response_body = {
                'zip_url': event_obj.zip_download_url,
                'created_at': album_zip.last_modified + "Z",
            }

            return self.create_response(request, response_body)
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")
        else:
            # check if there's already a job running that is creating an album archive
            if app.backend.get('event:{0}:create_album_zip'.format(
                    kwargs['pk'])):
                http409 = http.HttpResponse
                http409.status_code = 409
                return http409()
            else:
                event.create_album_zip.delay(kwargs['pk'])
                return http.HttpAccepted()
예제 #2
0
    def patch_detail(self, request, **kwargs):
        request = convert_post_to_patch(request)
        try:
            obj = self.cached_obj_get(request=request,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices('More than one resource'
                                            'is found at this URI.')

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)

        # Now update the bundle in-place.
        deserialized = self.deserialize(request,
                                        request.raw_post_data,
                                        format=request.META.get(
                                            'CONTENT_TYPE',
                                            'application/json'))

        # In case of a patch modification, we need to store
        # the initial values for the given object to check
        # the Etag header.
        request.initial_etag = bundle.obj.etag
        return self.create_patch_response(request, bundle, deserialized)
    def get_detail(self, request, **kwargs):
        """
        Returns a single serialized resource.

        Calls ``cached_obj_get/obj_get`` to provide the data, then handles that
        result set and serializes it.

        Should return a HttpResponse (200 OK).
        """
        try:
            # If call was made through Nested we should already have the
            # child object.
            if 'child_object' in kwargs:
                obj = kwargs.pop('child_object', None)
                if obj is None:
                    return http.HttpNotFound()
            else:
                obj = self.cached_obj_get(
                    request=request, **self.remove_api_resource_names(kwargs))
        except AttributeError:
            return http.HttpNotFound()
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found "
                                            "at this URI.")

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)
        return self.create_response(request, bundle)
예제 #4
0
    def get_detail(self, request, **kwargs):
        """
        Returns a single serialized resource.

        Calls ``cached_obj_get/obj_get`` to provide the data, then handles that result
        set and serializes it.

        Should return a HttpResponse (200 OK).
        """
        basic_bundle = self.build_bundle(request=request)

        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
        except (ObjectDoesNotExist, NotFound):
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        bundle = self.build_bundle(obj=obj, request=request)
        # add metadata to bundle to keep track of "depth", "ancestor" and "full" info
        bundle.related_info = bundle_related_data_info_factory(request=request)
        # end add
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)
        return self.create_response(request, bundle)
예제 #5
0
    def image_get(self, request, **kwargs):
        try:
            mol = self.cached_obj_get(**kwargs)
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found at this URI.")

        return self.render_image(mol, request, **kwargs)
예제 #6
0
    def patch_detail(self, request, **kwargs):
        """
        Updates a resource in-place.

        Calls ``obj_update``.

        If the resource is updated, return ``HttpAccepted`` (202 Accepted).
        If the resource did not exist, return ``HttpNotFound`` (404 Not Found).
        """
        request = convert_post_to_patch(request)
        basic_bundle = self.build_bundle(request=request)

        # We want to be able to validate the update, but we can't just pass
        # the partial data into the validator since all data needs to be
        # present. Instead, we basically simulate a PUT by pulling out the
        # original data and updating it in-place.
        # So first pull out the original object. This is essentially
        # ``get_detail``.
        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        self.post_obj_get(obj)

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)

        # Now update the bundle in-place.
        deserialized = self.deserialize(request,
                                        request.body,
                                        format=request.META.get(
                                            'CONTENT_TYPE',
                                            'application/json'))
        self.update_in_place(request, bundle, deserialized)
        # TODO: Check if this try/except is neccessary
        #try:
        #    self.update_in_place(request, bundle, deserialized)
        #except ObjectDoesNotExist:
        #    return http.HttpNotFound()
        #

        if not self._meta.always_return_data:
            return http.HttpAccepted()
        else:
            bundle = self.full_dehydrate(bundle)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return self.create_response(request,
                                        bundle,
                                        response_class=http.HttpAccepted)
    def get_detail_impl(self, request, base_bundle, **kwargs):
        try:
            obj, in_cache = self.cached_obj_get(
                bundle=base_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        frmt = request.format

        if frmt == 'png':
            self.answerBadRequest(
                request, 'PNG format has been deprecated, please use SVG.')

        if not frmt:
            if 'HTTP_ACCEPT' in request.META:
                if request.META['HTTP_ACCEPT'] == 'image/svg' or request.META[
                        'HTTP_ACCEPT'] == 'image/svg+xml':
                    frmt = 'svg'
                request.format = frmt

        if frmt in ['svg']:
            get_failed = False
            cache_key = self.generate_cache_key(
                'image', **dict({'is_ajax': request.is_ajax()}, **kwargs))
            ret = None
            try:
                ret = self._meta.cache.get(cache_key)
                in_cache = True
            except Exception:
                ret = None
                get_failed = True
                self.log.error('Cashing get exception',
                               exc_info=True,
                               extra=kwargs)

            if ret is None:
                in_cache = False
                ret = self.render_image(obj, request, **kwargs)
                if not get_failed:
                    try:
                        self._meta.cache.set(cache_key, ret)
                    except Exception:
                        self.log.error('Cashing set exception',
                                       exc_info=True,
                                       extra=kwargs)
            return ret, in_cache

        else:
            bundle = self.build_bundle(obj=obj, request=request)
            bundle = self.full_dehydrate(bundle, **kwargs)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return bundle, in_cache
예제 #8
0
    def dispatch_section_list(self, request, **kwargs):
        try:
            obj = self.cached_obj_get(request=request,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        section_resource = SectionResource()
        return section_resource.dispatch_list(request,
                                              story__story_id=obj.story_id)
예제 #9
0
    def dispatch_sectionasset_list(self, request, **kwargs):
        try:
            section_id = kwargs.pop('section_id')
            story = self.cached_obj_get(
                request=request, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        resource = SectionAssetResource()
        return resource.dispatch_list(request, section__section_id=section_id)
예제 #10
0
    def dispatch_files(self, request_type, request, **kwargs):
        obj_res = self.get_objects_resource(table_pk=kwargs.get('table_pk'))()
        obj_bundle = obj_res.build_bundle(request=request)
        try:
            obj = obj_res.cached_obj_get(bundle=obj_bundle, **kwargs)
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        proxy = self
        md = obj_res.get_model_definition()

        class R(ModelResource):
            class Meta:
                queryset = AttachedFile.objects.filter(content_type=md,
                                                       object_id=obj.pk)
                fields = ['id', 'file']
                list_allowed_methods = ['get', 'post', 'delete']
                detail_allowed_methods = ['get', 'delete']
                authorization = Authorization()

            def get_resource_uri(self, bundle_or_obj=None, **kwargs):
                kwargs = dict(table_pk=md.pk, object_pk=obj.pk)

                if bundle_or_obj:
                    kwargs['file_pk'] = self.detail_uri_kwargs(
                        bundle_or_obj).get('pk')
                    return proxy.uri_for_file_detail(**kwargs)
                else:
                    return proxy.uri_for_file_list(**kwargs)

            def authorized_create_detail(self, object_list, bundle):
                if obj_res.authorized_update_detail([obj], obj_bundle):
                    return object_list
                return []

            def authorized_delete_detail(self, object_list, bundle):
                return self.authorized_create_detail(object_list, bundle)

            def deserialize(self, request, data, format=None):
                return request.FILES

            def hydrate(self, bundle):
                bundle.obj.content_type = md
                bundle.obj.object_id = obj.pk
                return bundle

        return R().dispatch(request_type, request,
                            **{'pk': kwargs.get('file_pk')})
예제 #11
0
        def wrapper(resource, request, **kwargs):
            """ Wrapper for custom endpoints with boilerplate code. """
            # Tastypie API checks
            resource.method_check(request, allowed=expected_methods)
            resource.is_authenticated(request)
            resource.throttle_check(request)

            # Get object
            try:
                obj = resource._meta.queryset.get(uuid=kwargs['uuid'])
            except ObjectDoesNotExist:
                return http.HttpNotFound(
                    "Resource with UUID {} does not exist".format(
                        kwargs['uuid']))
            except MultipleObjectsReturned:
                return http.HttpMultipleChoices(
                    "More than one resource is found at this URI.")

            # Get body content
            try:
                deserialized = resource.deserialize(request,
                                                    request.body,
                                                    format=request.META.get(
                                                        'CONTENT_TYPE',
                                                        'application/json'))
                deserialized = resource.alter_deserialized_detail_data(
                    request, deserialized)
            except Exception:
                # Trouble decoding request body - may not actually exist
                deserialized = []

            # Check required fields, if any
            if not all(k in deserialized for k in required_fields):
                # Don't have enough information to make the request - return error
                return http.HttpBadRequest(
                    'All of these fields must be provided: {}'.format(
                        ', '.join(required_fields)))

            # Build bundle and return it
            bundle = resource.build_bundle(obj=obj,
                                           data=deserialized,
                                           request=request)
            bundle = resource.alter_detail_data_to_serialize(request, bundle)

            # Call the decorated method
            result = func(resource, request, bundle, **kwargs)
            resource.log_throttled_access(request)
            return result
예제 #12
0
    def patch_detail(self, request, **kwargs):
        """
        Updates a resource in-place.
        Calls ``obj_update``.
        If the resource is updated, return ``HttpAccepted`` (202 Accepted).
        If the resource did not exist, return ``HttpNotFound`` (404 Not Found).
        """
        # request = self.convert_post_to_patch(request)
        basic_bundle = self.build_bundle(request=request)

        # We want to be able to validate the update, but we can't just pass
        # the partial data into the validator since all data needs to be
        # present. Instead, we basically simulate a PUT by pulling out the
        # original data and updating it in-place.
        # So first pull out the original object. This is essentially
        # ``get_detail``.

        try:
            obj = self._meta.object_class.objects.get(id=kwargs['pk'])
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)

        # Now update the bundle in-place.
        deserialized = self.deserialize(request,
                                        request.body,
                                        format=request.META.get(
                                            'CONTENT_TYPE',
                                            'application/json'))
        self.update_in_place(request, bundle, deserialized)

        if not self._meta.always_return_data:
            return http.HttpAccepted()
        else:
            # Invalidate prefetched_objects_cache for bundled object
            # because we might have changed a prefetched field
            bundle.obj._prefetched_objects_cache = {}
            bundle = self.full_dehydrate(bundle)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return self.create_response(request,
                                        bundle,
                                        response_class=http.HttpAccepted)
예제 #13
0
    def dispatch_metadata_list(self, request, resource, **kwargs):
        """
        Dispatcher for nested resources that allow setting/replacing 
        story metadata

        """
        try:
            story = self.cached_obj_get(
                request=request, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        return resource.dispatch_list(request, story_id=story.story_id)
예제 #14
0
파일: api.py 프로젝트: IshaiJaffe/GeneG
 def post_register(self,request,**kwargs):
     try:
         username = request.POST.get('username')
         email = request.POST.get('email')
         if User.objects.filter(username=username).count():
             raise IntegrityError()
         password = request.POST.get('password')
         u = User.objects.create_user(username,email,password)
         apikey = ApiKey.objects.get(user=u)
         return self.create_response(request,{
                 'status':'success',
                 'username':u.username,
                 'email':u.email,
                 'api_key':apikey.key})
     except IntegrityError:
         return http.HttpMultipleChoices()
예제 #15
0
    def dispatch_sectionasset_list(self, request, **kwargs):
        try:
            section_id = kwargs.pop('section_id')
            # We fetch the story just to check that the
            # story_id to which the sub-resource is related
            # exists
            base_bundle = self.build_bundle(request=request)
            story = self.cached_obj_get(
                bundle=base_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        resource = SectionAssetResource()
        return resource.dispatch_list(request, section__section_id=section_id)
예제 #16
0
    def get_piece_likes(self, request, **kwargs):
        pk = kwargs['pk']
        try:
            bundle = self.build_bundle(data={'pk': pk}, request=request)
            obj = self.cached_obj_get(bundle=bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpGone()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        activities_resource = ActivityResource()
        return activities_resource.get_list(
            request,
            object_id=pk,
            content_type=ContentType.objects.get_for_model(bundle.obj),
            type='like')
예제 #17
0
    def dispatch_section_detail(self, request, **kwargs):
        try:
            # Remove the section id from the keyword arguments to lookup the
            # the story, saving it to pass to SectionResource.dispatch_detail
            # later
            section_id = kwargs.pop('section_id')
            obj = self.cached_obj_get(request=request,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        section_resource = SectionResource()
        return section_resource.dispatch_detail(request,
                                                story__story_id=obj.story_id,
                                                section_id=section_id)
예제 #18
0
    def get_detail(self, request, **kwargs):
        #applications = super(ApplicationResource, self).get_object_list(request)
        #return applications.filter(Q(tenant_id=request.user.account_id) | Q(owner_id=request.user.account_id))
        basic_bundle = self.build_bundle(request=request)

        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)
        return self.create_response(request, bundle)
예제 #19
0
    def get_detail(self, request, **kwargs):
        """
        Returns a single serialized resource.
        Calls ``cached_obj_get/obj_get`` to provide the data, then handles that result
        set and serializes it.
        Should return a HttpResponse (200 OK).
        """

        try:
            obj = self._meta.object_class.objects.get(id=kwargs['pk'])
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)
        return self.create_response(request, bundle)
예제 #20
0
    def obj_get(self, bundle, **kwargs):
        """
        Takes optional ``kwargs``, which are used to narrow the query to find
        the instance.

        Currently used to find one object from the url api/v1/resource/<pk>/

        Try to find an object using the pk
        """

        try:
            obj = self._meta.object_class.objects.get(id=kwargs['pk'])
        except ObjectDoesNotExist:
            msg = 'No {0} object found for id : {1}'\
                .format(self._meta.resource_name, kwargs['pk'])
            raise RhizomeApiException(message=msg, code=500)
        except MultipleObjectsReturned:
            raise http.HttpMultipleChoices("More than one resource found\
                at this URI.")

        return obj
예제 #21
0
    def attach_upload(self, request, resource_name, pk, **kwargs):
        """Attaches uploaded files to the resource"""

        try:
            obj = self.cached_obj_get(request=request,
                                      pk=pk,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        for field_name in getattr(self._meta, "uploads", []):
            uploaded_file = request.FILES.get(field_name, None)
            if uploaded_file is None:
                filename = request.GET['filename']
                uploaded_file = SimpleUploadedFile(filename, request.body)
            if uploaded_file is not None:
                setattr(obj, field_name, uploaded_file)
        obj.save()
        return HttpResponse()
예제 #22
0
    def _version_checks(self, request, **kwargs):
        """
        Runs the same validation and auth checks as would be run for the
        parent resource get detail view.
        """
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)
        self.log_throttled_access(request)

        basic_bundle = self.build_bundle(request=request)

        try:
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found at this URI.")

        bundle = self.build_bundle(request=request)
        self.authorized_read_detail(self.get_object_list(bundle.request), bundle)
        return obj
예제 #23
0
    def post_detail(self, request, **kwargs):
        if 'ssh_key' not in request.FILES:
            res = HttpResponse("Please upload an ssh_key file")
            res.status_code = 500
            return res

        basic_bundle = self.build_bundle(request=request)

        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        ssh_key = request.FILES['ssh_key']
        got = ssh_key.read()
        ssh_key.seek(0)
        try:
            SSHKey(got, obj.password).key_obj
        except paramiko.ssh_exception.SSHException as error:
            res = HttpResponse(error)
            res.status_code = 500
            return res

        obj.ssh_key = File(ssh_key)
        obj.save()

        if not self._meta.always_return_data:
            return http.HttpAccepted()
        else:
            bundle = self.build_bundle(obj=obj, request=request)
            bundle = self.full_dehydrate(bundle)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return self.create_response(request,
                                        bundle,
                                        response_class=http.HttpAccepted)
예제 #24
0
    def attach_upload(self, request, resource_name, pk, **kwargs):
        """Attaches uploaded files to the resource"""

        try:
            obj = self.cached_obj_get(request=request,
                                      pk=pk,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        for field_name in getattr(self._meta, "uploads", []):
            uploaded_file = request.FILES.get(field_name, None)
            if uploaded_file is not None:
                setattr(obj, field_name, uploaded_file)
        obj.save()
        bundle = self.build_bundle(obj=obj, request=request)
        bundle = self.full_dehydrate(bundle)
        bundle = self.alter_detail_data_to_serialize(request, bundle)
        return self.create_response(request, bundle, http.HttpAccepted)
예제 #25
0
 def post_invites(self, request, **kwargs):
     ### start copied from tasytpie ###
     body = request.body
     deserialized = self.deserialize(request,
                                     body,
                                     format=request.META.get(
                                         'CONTENT_TYPE',
                                         'application/json'))
     deserialized = self.alter_deserialized_detail_data(
         request, deserialized)
     bundle = self.build_bundle(data=dict_strip_unicode_keys(deserialized),
                                request=request)
     ## start custom code ##
     try:
         event_obj = Event.objects.get(pk=kwargs['pk'])
     except ObjectDoesNotExist:
         return http.HttpNotFound()
     except MultipleObjectsReturned:
         return http.HttpMultipleChoices(
             "More than one resource is found at this URI.")
     else:
         event.email_guests.delay(kwargs['pk'], bundle.data['message'])
         return http.HttpAccepted()
예제 #26
0
파일: api.py 프로젝트: rma945/CryptoRatt
    def post_detail(self, request, **kwargs):
        basic_bundle = self.build_bundle(request=request)

        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found at this URI.")

        obj.save()

        if not self._meta.always_return_data:
            return http.HttpAccepted()
        else:
            bundle = self.build_bundle(obj=obj, request=request)
            bundle = self.full_dehydrate(bundle)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return self.create_response(request,
                                        bundle,
                                        response_class=http.HttpAccepted)
예제 #27
0
    def check_etag(self, request, **kwargs):
        basic_bundle = self.build_bundle(request=request)
        try:
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one resource is found at this URI.")

        # Not a great implementation... but probably good enough to
        # prevent edit conflicts. Compulsory MD5 etags make it
        # difficult to use collections and nested resource.
        slack_etags = True

        if self.can_etag(obj):
            etag_to_match = request.META.get('HTTP_IF_MATCH', '').strip()
            if etag_to_match:
                current_etag = self.calc_etag(request, obj)
                if etag_to_match != current_etag:
                    return HttpPreconditionFailed("Etag mismatch")
            elif not slack_etags:
                return HttpPreconditionRequired("Please use If-Match")

        return None
예제 #28
0
    def post_list(self, request, **kwargs):
        """
        Creates a new resource/object with the provided data.

        Calls ``obj_create`` with the provided data and returns a response
        with the new resource's location.

        If a new resource is created, return ``HttpCreated`` (201 Created).
        If ``Meta.always_return_data = True``, there will be a populated body
        of serialized data.
        """

        basic_bundle = self.build_bundle(request=request)

        deserialized = self.deserialize(request,
                                        request.body,
                                        format=request.META.get(
                                            'CONTENT_TYPE',
                                            'application/json'))
        deserialized = self.alter_deserialized_detail_data(
            request, deserialized)

        exclude_from_match = ['description', 'api_name']

        # Build the item match terms
        for field, value in deserialized.iteritems():
            print "field is", field
            if field not in exclude_from_match:
                kwargs[field] = value

        # If the object already exists then return it instead of creating a new one
        try:
            obj = self.cached_obj_get(bundle=basic_bundle,
                                      **self.remove_api_resource_names(kwargs))
            bundle = self.build_bundle(obj=obj, request=request)
            bundle = self.full_dehydrate(bundle)
            bundle = self.alter_detail_data_to_serialize(request, bundle)
            return self.create_response(request, bundle)
        except ObjectDoesNotExist:
            sys.exc_clear()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices(
                "More than one resource is found with these details.")

        bundle = self.build_bundle(data=dict_strip_unicode_keys(deserialized),
                                   request=request)
        #raise Exception("I think we've gone far enough in post, don't you?")
        updated_bundle = self.obj_create(
            bundle, **self.remove_api_resource_names(kwargs))
        location = self.get_resource_uri(updated_bundle)

        if not self._meta.always_return_data:
            return http.HttpCreated(location=location)
        else:
            updated_bundle = self.full_dehydrate(updated_bundle)
            updated_bundle = self.alter_detail_data_to_serialize(
                request, updated_bundle)
            return self.create_response(request,
                                        updated_bundle,
                                        response_class=http.HttpCreated,
                                        location=location)
예제 #29
0
    def process_file(self, request, **kwargs):
        """
        :param request:     incoming http request
        :param pk:          ID of the object that has file fields
        :param attr_name:   name of the attribute where the file is stored
        :return:            Http Response
        """
        attr_name = kwargs.pop('attr_name')

        if not request.method in ['GET', 'POST']:
            return http.HttpMethodNotAllowed("Use GET or POST to manage files")

        try:
            bundle = self.build_bundle(data={'pk': kwargs['pk']},
                                       request=request)
            obj = self.cached_obj_get(bundle=bundle,
                                      **self.remove_api_resource_names(kwargs))

        except ObjectDoesNotExist:
            return http.HttpGone()

        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one object found "
                                            "at this URL.")
        try:
            field = self._meta.object_class._meta.get_field_by_name(
                attr_name)[0]

        except FieldDoesNotExist:
            return http.HttpBadRequest("Attribute %s does not exist" %
                                       attr_name)

        if not isinstance(field, models.FileField):
            return http.HttpBadRequest("Attribute %s is not a data-field" %
                                       attr_name)

        if request.method == 'GET':
            ffile = getattr(obj, attr_name)
            try:
                filepath = ffile.path
            except ValueError:  # file is not set, empty
                return http.HttpNoContent()

            with open(filepath, 'r') as f:
                response = HttpResponse(f.read(),
                                        content_type='application/x-hdf')
                response['Content-Disposition'] = "attachment; filename=%s" % \
                                                  os.path.basename(filepath)
                response['Content-Length'] = os.path.getsize(f.name)
                return response

        if not obj.is_editable(request.user):
            return http.HttpUnauthorized("No access to the update this object")

        if not len(request.FILES) > 0:
            return http.HttpNoContent()

        # take first file in the multipart/form request
        setattr(obj, attr_name, request.FILES.values()[0])
        obj.save()
        return http.HttpAccepted("File content updated successfully")
    def dispatch_nested(self, request, **kwargs):
        """
        Dispatch a request to the nested resource.
        """
        # We don't check for is_authorized here since it will be
        # parent_cached_obj_get which will check that we have permissions
        # over the parent.
        self.is_authenticated(request)
        self.throttle_check(request)

        nested_name = kwargs.pop('nested_name')
        nested_field = self._nested[nested_name]

        try:
            obj = self.parent_cached_obj_get(
                request=request, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return http.HttpNotFound()
        except MultipleObjectsReturned:
            return http.HttpMultipleChoices("More than one parent resource is "
                                            "found at this URI.")

        # The nested resource needs to get the api_name from its parent because
        # it is possible that the resource being used as nested is not
        # registered in the API (ie. it can only be used as nested)
        nested_resource = nested_field.to_class()
        nested_resource._meta.api_name = self._meta.api_name

        # TODO: comment further to make sense of this block
        manager = None
        try:
            if isinstance(nested_field.attribute, basestring):
                name = nested_field.attribute
                manager = getattr(obj, name, None)
            elif callable(nested_field.attribute):
                manager = nested_field.attribute(obj)
            else:
                raise fields.ApiFieldError(
                    "The model '%r' has an empty attribute '%s' \
                    and doesn't allow a null value." %
                    (obj, nested_field.attribute))
        except ObjectDoesNotExist:
            pass

        kwargs['nested_name'] = nested_name
        kwargs['parent_resource'] = self
        kwargs['parent_object'] = obj

        if manager is None or not hasattr(manager, 'all'):
            dispatch_type = 'detail'
            kwargs['child_object'] = manager
        else:
            dispatch_type = 'list'
            kwargs['related_manager'] = manager
            # 'pk' will refer to the parent, so we remove it.
            if 'pk' in kwargs:
                del kwargs['pk']
            # Update with the related manager's filters, which will link to
            # the parent.
            kwargs.update(manager.core_filters)

        return nested_resource.dispatch(dispatch_type, request, **kwargs)