resource=resource, source_entity__string_hash=source_hash, language=language ) if not translations: return rc.NOT_FOUND field_map = self._get_fieldmap() fields = self._get_fields_for_translation_value_query_set(field_map) return self._generate_translations_dict( translations.values(*fields), field_map, True ) @require_mime('json') @throttle(settings.API_MAX_REQUESTS, settings.API_THROTTLE_INTERVAL) @method_decorator(one_perm_required_or_403( pr_project_private_perm, (Project, 'slug__exact', 'project_slug') )) def update(self, request, project_slug, resource_slug, language_code, source_hash, api_version=2): """ Update existing translations for a source entity of a resource. """ try: project, resource, language = \ self._requested_objects(project_slug, resource_slug, language_code) # A translation in source language cannot be updated self._validate_language_is_not_source_language( project.source_language, language) try: source_entity = SourceEntity.objects.get(
" as well as the source strings." ) try: res = self._create(request, project_slug, data) except BadRequestError, e: return BAD_REQUEST(unicode(e)) except NotFoundError, e: return rc.NOT_FOUND t = Translation.get_object("create", request) res = t.__class__.to_http_for_create(t, res) if res.status_code == 200: res.status_code = 201 return res @require_mime('json') @method_decorator(one_perm_required_or_403(pr_resource_add_change, (Project, 'slug__exact', 'project_slug'))) def update(self, request, project_slug, resource_slug=None, api_version=1): """ API call to update resource details via PUT """ if resource_slug is None: return BAD_REQUEST("No resource specified in url") return self._update(request, project_slug, resource_slug) @method_decorator(one_perm_required_or_403(pr_resource_delete, (Project, 'slug__exact', 'project_slug'))) def delete(self, request, project_slug, resource_slug=None, api_version=1): """ API call to delete resources via DELETE. """ if resource_slug is None:
try: template = _compile_translation_template(resource, language) except Exception, e: logger.error(e.message, exc_info=True) return BAD_REQUEST("Error compiling the translation file: %s" %e ) i18n_method = settings.I18N_METHODS[resource.i18n_type] response = HttpResponse(template, mimetype=i18n_method['mimetype']) response['Content-Disposition'] = ('attachment; filename*="UTF-8\'\'%s_%s%s"' % ( urllib.quote(resource.name.encode('UTF-8')), language.code, i18n_method['file-extensions'].split(', ')[0])) return response @method_decorator(one_perm_required_or_403( pr_resource_translations_delete, (Project, "slug__exact", "project_slug"))) def delete(self, request, project_slug, resource_slug=None, language_code=None, api_version=1): """ DELETE requests for translations. """ try: resource = Resource.objects.get( slug=resource_slug, project__slug=project_slug ) except Resource.DoesNotExist, e: return rc.NOT_FOUND # Error message to use in case user asked to # delete the source translation
class ProjectHandler(BaseHandler): """ API handler for model Project. """ allowed_methods = ('GET', 'POST', 'PUT', 'DELETE') details_fields = ( 'slug', 'name', 'description', 'long_description', 'homepage', 'feed', 'created', 'anyone_submit', 'bug_tracker', 'trans_instructions', 'tags', 'outsource', ('maintainers', ('username', )), ('owner', ('username', )), ('resources', ( 'slug', 'name', )), 'teams', 'source_language_code', ) default_fields = ( 'slug', 'name', 'description', 'source_language_code', ) fields = default_fields allowed_fields = ( 'name', 'slug', 'description', 'long_description', 'private', 'homepage', 'feed', 'anyone_submit', 'hidden', 'bug_tracker', 'trans_instructions', 'tags', 'maintainers', 'outsource', 'source_language_code', ) exclude = () @classmethod def source_language_code(cls, p): """Add the source language as a field.""" return p.source_language.code @classmethod def teams(cls, p): """Show the language codes for which there are teams as list. Return an empty list in case there are no teams defined. """ team_set = get_project_teams(p) return team_set.values_list('language__code', flat=True) def read(self, request, project_slug=None, api_version=1): """ Get project details in json format """ # Reset fields to default value ProjectHandler.fields = ProjectHandler.default_fields if "details" in request.GET.iterkeys(): if project_slug is None: return rc.NOT_IMPLEMENTED ProjectHandler.fields = ProjectHandler.details_fields return self._read(request, project_slug) @require_mime('json') @method_decorator(one_perm_required_or_403(pr_project_add)) def create(self, request, project_slug=None, api_version=1): """ API call to create new projects via POST. """ data = getattr(request, 'data', None) if project_slug is not None: return BAD_REQUEST("POSTing to this url is not allowed.") if data is None: return BAD_REQUEST("At least parameters 'slug', 'name' and " "'source_language' are needed.") return self._create(request, data) @require_mime('json') @method_decorator( one_perm_required_or_403(pr_project_add_change, (Project, 'slug__exact', 'project_slug'))) def update(self, request, project_slug, api_version=1): """ API call to update project details via PUT. """ if project_slug is None: return BAD_REQUEST("Project slug not specified.") data = request.data if data is None: return BAD_REQUEST("Empty request.") return self._update(request, project_slug, data) @method_decorator( one_perm_required_or_403(pr_project_delete, (Project, 'slug__exact', 'project_slug'))) def delete(self, request, project_slug=None, api_version=1): """ API call to delete projects via DELETE. """ if project_slug is None: return BAD_REQUEST("Project slug not specified.") return self._delete(request, project_slug) def _read(self, request, project_slug): """ Return a list of projects or the details for a specific project. """ if project_slug is None: # Use pagination p = Project.objects.for_user(request.user) res, msg = paginate(p, request.GET.get('start'), request.GET.get('end')) if res is None: return BAD_REQUEST(msg) return res else: try: p = Project.objects.get(slug=project_slug) perm = ProjectPermission(request.user) if not perm.private(p): return rc.FORBIDDEN except Project.DoesNotExist: return rc.NOT_FOUND return p def _create(self, request, data): """ Create a new project. """ mandatory_fields = ( 'slug', 'name', 'source_language_code', ) msg = "Field '%s' is required to create a project." for field in mandatory_fields: if field not in data: return BAD_REQUEST(msg % field) if 'owner' in data: return BAD_REQUEST("Owner cannot be set explicitly.") try: self._check_fields(data.iterkeys()) except AttributeError, e: return BAD_REQUEST("Field '%s' is not available." % e.message) # outsource and maintainers are ForeignKey outsource = data.pop('outsource', {}) maintainers = data.pop('maintainers', {}) lang = data.pop('source_language_code') try: source_language = Language.objects.by_code_or_alias(lang) except Language.DoesNotExist: return BAD_REQUEST("Language %s does not exist." % lang) try: p = Project(**data) p.source_language = source_language except Exception: return BAD_REQUEST("Invalid arguments given.") try: p.full_clean() except ValidationError, e: return BAD_REQUEST("%s" % e)
class ResourceHandler(BaseHandler): """ Resource Handler for CRUD operations. """ @classmethod def project_slug(cls, sfk): """ This is a work around to include the project slug in the resource API details, so that it is shown as a normal field. """ if sfk.project: return sfk.project.slug return None @classmethod def mimetype(cls, r): """ Return the mimetype in a GET request instead of the i18n_type. """ return registry.mimetypes_for(r.i18n_method)[0] @classmethod def source_language_code(cls, r): """ Return just the code of the source language. """ return r.source_language.code allowed_methods = ('GET', 'POST', 'PUT', 'DELETE') default_fields = ( 'slug', 'name', 'i18n_type', 'source_language_code', 'category', ) details_fields = ( 'slug', 'name', 'created', 'available_languages', 'i18n_type', 'source_language_code', 'project_slug', 'wordcount', 'total_entities', 'accept_translations', 'last_update', 'category', ) fields = default_fields allowed_fields = ( 'slug', 'name', 'accept_translations', 'i18n_type', 'content', 'category', ) written_fields = ( 'slug', 'name', 'accept_translations', 'content', 'category', ) apiv1_fields = ('slug', 'name', 'created', 'available_languages', 'i18n_type', 'source_language', 'project_slug') exclude = () def read(self, request, project_slug, resource_slug=None, api_version=1): """ Get details of a resource. """ # Reset fields to default value ResourceHandler.fields = self.default_fields if "details" in request.GET: if resource_slug is None: return rc.NOT_IMPLEMENTED ResourceHandler.fields = ResourceHandler.details_fields return self._read(request, project_slug, resource_slug) @method_decorator( one_perm_required_or_403(pr_resource_add_change, (Project, 'slug__exact', 'project_slug'))) def create(self, request, project_slug, resource_slug=None, api_version=1): """ Create new resource under project `project_slug` via POST """ data = getattr(request, 'data', None) if resource_slug is not None: return BAD_REQUEST("POSTing to this url is not allowed.") if data is None: return BAD_REQUEST( "At least parameters 'slug', 'name', 'i18n_type' " "and 'source_language' must be specified," " as well as the source strings.") try: res = self._create(request, project_slug, data) except BadRequestError, e: return BAD_REQUEST(unicode(e)) except NotFoundError, e: return rc.NOT_FOUND
class TranslationHandler(BaseHandler): allowed_methods = ( 'GET', 'PUT', 'DELETE', ) @throttle(settings.API_MAX_REQUESTS, settings.API_THROTTLE_INTERVAL) @method_decorator( one_perm_required_or_403(pr_project_private_perm, (Project, 'slug__exact', 'project_slug'))) def read(self, request, project_slug, resource_slug, lang_code=None, is_pseudo=None, api_version=2): return self._read(request, project_slug, resource_slug, lang_code, is_pseudo) @throttle(settings.API_MAX_REQUESTS, settings.API_THROTTLE_INTERVAL) def update(self, request, project_slug, resource_slug, lang_code, api_version=2): return self._update(request, project_slug, resource_slug, lang_code) @method_decorator( one_perm_required_or_403(pr_resource_translations_delete, (Project, "slug__exact", "project_slug"))) def delete(self, request, project_slug, resource_slug, lang_code=None, api_version=2): return self._delete(request, project_slug, resource_slug, lang_code) def _read(self, request, project_slug, resource_slug, lang_code, is_pseudo): try: r = Resource.objects.get(slug=resource_slug, project__slug=project_slug) except Resource.DoesNotExist: return rc.NOT_FOUND if lang_code == "source": language = r.source_language else: try: language = Language.objects.by_code_or_alias(lang_code) except Language.DoesNotExist: return rc.NOT_FOUND # Check whether the request asked for a pseudo file, if so check if # a ``pseudo_type`` GET var was passed with a valid pseudo type. if is_pseudo: ptype = request.GET.get('pseudo_type', None) if not ptype in settings.PSEUDO_TYPES.keys(): return rc.NOT_FOUND # Instantiate Pseudo type object pseudo_type = get_pseudo_class(ptype)(r.i18n_type) else: pseudo_type = None # Get the mode the user requested, if any mode = request.GET.get('mode', None) if mode is not None: try: mode = getattr(Mode, mode.upper()) except AttributeError, e: return BAD_REQUEST(unicode(e)) translation = Translation.get_object("get", request, r, language) try: res = translation.get(pseudo_type=pseudo_type, mode=mode) except BadRequestError, e: return BAD_REQUEST(unicode(e))
" as well as the source strings.") try: res = self._create(request, project_slug, data) except BadRequestError, e: return BAD_REQUEST(unicode(e)) except NotFoundError, e: return rc.NOT_FOUND t = Translation.get_object("create", request) res = t.__class__.to_http_for_create(t, res) if res.status_code == 200: res.status_code = 201 return res @require_mime('json') @method_decorator( one_perm_required_or_403(pr_resource_add_change, (Project, 'slug__exact', 'project_slug'))) def update(self, request, project_slug, resource_slug=None, api_version=1): """ API call to update resource details via PUT """ if resource_slug is None: return BAD_REQUEST("No resource specified in url") return self._update(request, project_slug, resource_slug) @method_decorator( one_perm_required_or_403(pr_resource_delete, (Project, 'slug__exact', 'project_slug'))) def delete(self, request, project_slug, resource_slug=None, api_version=1): """ API call to delete resources via DELETE. """