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()
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)
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)
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)
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
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)
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)
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')})
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
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)
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)
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()
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)
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')
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)
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)
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)
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
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()
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
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)
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)
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()
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)
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
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)
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)