class BackendResource(ModelResource): dc = fields.ForeignKey(DcResource, 'dc', full=True) director = fields.ForeignKey(DirectorResource, 'director') tags = ListField() class Meta: queryset = Backend.objects.all() resource_name = 'backend' serializer = PrettyJSONSerializer() authorization = DjangoAuthorization() authentication = VaasMultiAuthentication(ApiKeyAuthentication()) validation = ModelCleanedDataFormValidation( form_class=BackendModelForm) always_return_data = True filtering = { 'dc': ALL_WITH_RELATIONS, 'director': ALL_WITH_RELATIONS, 'address': ['exact'], 'port': ['exact'] } def dehydrate(self, bundle): status = BackendStatus.objects.filter(address=bundle.data['address'], port=bundle.data['port']) if len(status) > 0: bundle.data['status'] = status[0].status else: bundle.data['status'] = "Unknown" bundle.data['time_profile'] = { 'max_connections': bundle.obj.director.time_profile.max_connections, 'connect_timeout': bundle.obj.director.time_profile.connect_timeout, 'first_byte_timeout': bundle.obj.director.time_profile.first_byte_timeout, 'between_bytes_timeout': bundle.obj.director.time_profile.between_bytes_timeout } return bundle def build_filters(self, filters=None, ignore_bad_filters=False): if filters is None: filters = {} orm_filters = super(BackendResource, self).build_filters( filters, ignore_bad_filters=ignore_bad_filters) if 'tag' in filters: orm_filters['tags__name__in'] = filters['tag'].split(',') return orm_filters def dehydrate_tags(self, bundle): return list(map(str, bundle.obj.tags.all())) def hydrate_tags(self, bundle): if isinstance(bundle.data.get('tags'), list): bundle.data['tags'] = ','.join(bundle.data['tags']) elif bundle.data.get('tags') is None: bundle.data['tags'] = '' return bundle def save_m2m(self, bundle): tags = bundle.data.get('tags', []) bundle.obj.tags.set(*tags) return super(BackendResource, self).save_m2m(bundle)
class PressReleaseResource(ModelResource): issue_uri = fields.ForeignKey(IssueResource, 'issue') translations = fields.OneToManyField(PressReleaseTranslationResource, 'translations', full=True) articles = fields.CharField(readonly=True) issue_meta = fields.CharField(readonly=True) class Meta(ApiKeyAuthMeta): resource_name = 'pressreleases' queryset = RegularPressRelease.objects.all() allowed_methods = [ 'get', ] ordering = ['id'] def build_filters(self, filters=None): """ Custom filter that retrieves data by the article PID. """ if filters is None: filters = {} orm_filters = super(PressReleaseResource, self).build_filters(filters) if 'article_pid' in filters: preleases = RegularPressRelease.objects.filter( articles__article_pid=filters['article_pid']) orm_filters['pk__in'] = preleases elif 'journal_pid' in filters: preleases = RegularPressRelease.objects.by_journal_pid( filters['journal_pid']) orm_filters['pk__in'] = preleases elif 'issue_pid' in filters: preleases = RegularPressRelease.objects.by_issue_pid( filters['issue_pid']) orm_filters['pk__in'] = preleases return orm_filters def dehydrate_articles(self, bundle): return [art.article_pid for art in bundle.obj.articles.all()] def dehydrate_issue_meta(self, bundle): issue = bundle.obj.issue meta_data = { 'scielo_pid': issue.scielo_pid, 'short_title': issue.journal.short_title, 'volume': issue.volume, 'number': issue.number, 'suppl_volume': issue.suppl_text if issue.type == 'supplement' and issue.volume else '', 'suppl_number': issue.suppl_text if issue.type == 'supplement' and issue.number else '', 'publication_start_month': issue.publication_start_month, 'publication_end_month': issue.publication_end_month, 'publication_city': issue.journal.publication_city, 'publication_year': issue.publication_year, } return meta_data
class BaseAbuseResource(PotatoCaptchaResource, CORSResource, MarketplaceResource): """ Base resource for abuse reports. """ text = fields.CharField(attribute='text') ip_address = fields.CharField(attribute='ip_address', blank=True) reporter = fields.ForeignKey(AccountResource, attribute='reporter', null=True, full=True) class Meta(MarketplaceResource.Meta): always_return_data = True list_allowed_methods = ['post'] detail_allowed_methods = [] authentication = OptionalOAuthAuthentication() authorization = Authorization() object_class = GenericObject include_resource_uri = False validation_form = None rename_field_map = [ ('text', 'message'), ] throttle = CacheThrottle(throttle_at=30) def obj_create(self, bundle, request=None, **kwargs): bundle.obj = self._meta.object_class(**kwargs) bundle = self.full_hydrate(bundle) self.remove_potato(bundle) AbuseReport.objects.create(**self.rename_fields(bundle)).send() return bundle def get_resource_uri(self, bundle_or_obj=None): """ Noop needed to prevent NotImplementedError. """ return '' def hydrate(self, bundle): """ Add the authenticated user to the bundle. """ bundle.data.update({ 'reporter': bundle.request.amo_user, 'ip_address': bundle.request.META.get('REMOTE_ADDR', '') }) return bundle def dehydrate(self, bundle): """ Strip the `ip_address` field before presenting to the consumer. """ del bundle.data['ip_address'] return bundle def rename_fields(self, bundle): """ Rename fields as defined in Meta.rename_field_map. Used to rename fields in the bundle before sending to Model.objects.create(). """ data = bundle.data.copy() for old, new in self._meta.rename_field_map: data[new] = data[old] del data[old] return data
class TrackerResource(ModelResource): ''' Submitting a Tracker ''' user = fields.ForeignKey(UserResource, 'user') points = fields.IntegerField(readonly=True) badges = fields.IntegerField(readonly=True) scoring = fields.BooleanField(readonly=True) badging = fields.BooleanField(readonly=True) metadata = fields.CharField(readonly=True) course_points = fields.CharField(readonly=True) class Meta: queryset = Tracker.objects.all() resource_name = 'tracker' allowed_methods = ['post', 'patch'] detail_allowed_methods = ['post', 'patch'] authentication = ApiKeyAuthentication() authorization = Authorization() serializer = PrettyJSONSerializer() always_return_data = True fields = [ 'points', 'digest', 'data', 'tracker_date', 'badges', 'course', 'completed', 'scoring', 'metadata', 'badging' ] validation = TrackerValidation() def process_tracker_bundle(self, bundle): try: if 'course' in bundle.data: media_objs = Media.objects.filter( digest=bundle.data['digest'], course__shortname=bundle.data['course'])[:1] else: media_objs = Media.objects.filter( digest=bundle.data['digest'])[:1] if media_objs.count() > 0: media = media_objs[0] bundle.obj.course = media.course bundle.obj.type = 'media' except Media.DoesNotExist: pass try: json_data = json.loads(bundle.data['data']) if 'timetaken' in json_data: bundle.obj.time_taken = json_data['timetaken'] if 'uuid' in json_data: bundle.obj.uuid = json_data['uuid'] if 'lang' in json_data: bundle.obj.lang = json_data['lang'] except ValueError: pass except KeyError: pass if 'points' in bundle.data: bundle.obj.points = bundle.data['points'] if 'event' in bundle.data: bundle.obj.event = bundle.data['event'] return bundle def hydrate(self, bundle, request=None): # remove any id if this is submitted - otherwise it may overwrite existing tracker item if 'id' in bundle.data: del bundle.obj.id bundle.obj.user = bundle.request.user bundle.obj.ip = bundle.request.META.get('REMOTE_ADDR', api.DEFAULT_IP_ADDRESS) bundle.obj.agent = bundle.request.META.get('HTTP_USER_AGENT', 'unknown') if 'type' in bundle.data and bundle.data['type'] == 'search': # if the tracker is a search, we just need to save it bundle.obj.course = None bundle.obj.type = "search" return bundle # find out the course & activity type from the digest try: if 'course' in bundle.data: activities = Activity.objects.filter( digest=bundle.data['digest'], section__course__shortname=bundle.data['course'])[:1] else: activities = Activity.objects.filter( digest=bundle.data['digest'])[:1] if activities.count() > 0: activity = activities[0] bundle.obj.course = activity.section.course bundle.obj.type = activity.type bundle.obj.activity_title = activity.title bundle.obj.section_title = activity.section.title else: bundle.obj.course = None bundle.obj.type = '' bundle.obj.activity_title = '' bundle.obj.section_title = '' except Activity.DoesNotExist: bundle.obj.course = None bundle.obj.type = '' bundle.obj.activity_title = '' bundle.obj.section_title = '' bundle = self.process_tracker_bundle(bundle) return bundle def hydrate_tracker_date(self, bundle, request=None, **kwargs): # Fix tracker date if date submitted is in the future if 'tracker_date' in bundle.data: tracker_date = dateparse.parse_datetime( bundle.data['tracker_date']) if tracker_date > datetime.datetime.now(): bundle.data['tracker_date'] = timezone.now() return bundle def dehydrate_points(self, bundle): points = Points.get_userscore(bundle.request.user) return points def dehydrate_badges(self, bundle): badges = Award.get_userawards(bundle.request.user) return badges def dehydrate_scoring(self, bundle): return settings.OPPIA_POINTS_ENABLED def dehydrate_badging(self, bundle): return settings.OPPIA_BADGES_ENABLED def dehydrate_metadata(self, bundle): return settings.OPPIA_METADATA def dehydrate_course_points(self, bundle): course_points = list( Points.objects.exclude(course=None).filter( user=bundle.request.user).values('course__shortname').annotate( total_points=Sum('points'))) return course_points def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) for data in deserialized["objects"]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META['REMOTE_ADDR'] = request.META.get( 'REMOTE_ADDR', api.DEFAULT_IP_ADDRESS) bundle.request.META['HTTP_USER_AGENT'] = request.META.get( 'HTTP_USER_AGENT', 'unknown') # check UUID not already submitted if 'data' in bundle.data: json_data = json.loads(bundle.data['data']) if 'uuid' in json_data: uuids = Tracker.objects.filter(uuid=json_data['uuid']) if uuids.count() == 0: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) response_data = { 'points': self.dehydrate_points(bundle), 'badges': self.dehydrate_badges(bundle), 'scoring': self.dehydrate_scoring(bundle), 'badging': self.dehydrate_badging(bundle), 'metadata': self.dehydrate_metadata(bundle), 'course_points': self.dehydrate_course_points(bundle), } response = HttpResponse(content=json.dumps(response_data), content_type="application/json; charset=utf-8") return response
class PipelineTemplateResource(ModelResource): data = fields.ForeignKey(SnapshotResource, 'snapshot') class Meta: queryset = PipelineTemplate.objects.filter(is_deleted=False) resource_name = 'templates' excludes = ['is_deleted'] always_return_data = True detail_uri_name = 'template_id' list_allowed_methods = ['get', 'post'] detail_allowed_methods = ['get', 'patch', 'post', 'delete'] filtering = { 'template_id': ALL_WITH_RELATIONS, } authorization = Authorization() serializer = PipelineSerializer() validation = FormValidation(form_class=forms.PipelineTemplateForm) def dehydrate_data(self, bundle): return json.dumps(bundle.obj.snapshot.data) def hydrate(self, bundle): pop_keys = ['template_id', 'create_time', 'edit_time', 'version'] for key in pop_keys: if key in bundle.data: bundle.data.pop(key) return super(PipelineTemplateResource, self).hydrate(bundle) def obj_update(self, bundle, skip_errors=False, **kwargs): json_data = bundle.data['data'] try: data = json.loads(json_data) except Exception: raise_validation_error(self, bundle, 'templates', 'data', _(u"JSON 格式不合法")) result, msg = self.subprocess_ref_validate( bundle, data, root_id=bundle.obj.template_id, root_name=bundle.obj.name) if not result: raise_validation_error(self, bundle, 'templates', 'data', msg) self.gateway_validate(bundle, data) bundle.obj.snapshot, __ = Snapshot.objects.create_or_get_snapshot(data) bundle.data.pop('data') return super(PipelineTemplateResource, self).obj_update(bundle, skip_errors=skip_errors, **kwargs) def obj_create(self, bundle, **kwargs): json_data = bundle.data.get('data') try: data = json.loads(json_data) except Exception: raise_validation_error(self, bundle, 'templates', 'data', _(u"JSON 格式不合法")) result, msg = self.subprocess_ref_validate(bundle, data) if not result: raise_validation_error(self, bundle, 'templates', 'data', msg) self.gateway_validate(bundle, data) snapshot, __ = Snapshot.objects.create_or_get_snapshot(data) kwargs['snapshot_id'] = snapshot.id kwargs['template_id'] = node_uniqid() # must pop data field after the creation of snapshot is finished. bundle.data.pop('data') return super(PipelineTemplateResource, self).obj_create(bundle, **kwargs) def obj_delete(self, bundle, **kwargs): template_id = kwargs['template_id'] PipelineTemplate.objects.delete_model(template_id) def alter_list_data_to_serialize(self, request, data): for bundle in data['objects']: bundle.data.pop('id') bundle.data.pop('data') bundle.data.pop('description') bundle.data['version'] = bundle.obj.pipeline_template.version bundle.data[ 'subprocess_has_update'] = bundle.obj.pipeline_template.subprocess_has_update return data def alter_detail_data_to_serialize(self, request, data): bundle = data bundle.data.pop('id') bundle.data[ 'subprocess_version_info'] = bundle.obj.pipeline_template.subprocess_version_info return data def gateway_validate(self, bundle, data): try: validate_converge_gateway(data) except exceptions.ConvergeMatchError as e: raise_validation_error(self, bundle, 'templates', 'data', e.message)
class ActivityResource(ModelResource): countries = fields.ToManyField(OnlyCountryResource, 'recipient_country', full=True, null=True, use_in='all') regions = fields.ToManyField(OnlyRegionResource, 'recipient_region', full=True, null=True, use_in='all') sectors = fields.ToManyField(ActivityViewSectorResource, 'sector', full=True, null=True, use_in='all') titles = fields.ToManyField(TitleResource, 'title_set', full=True, null=True, use_in='all') descriptions = fields.ToManyField(DescriptionResource, 'description_set', full=True, null=True, use_in='all') participating_organisations = fields.ToManyField( ActivityViewOrganisationResource, 'participating_organisation', full=True, null=True, use_in='all') reporting_organisation = fields.ForeignKey( ActivityViewOrganisationResource, 'reporting_organisation', full=True, null=True, use_in='detail') activity_status = fields.ForeignKey(ActivityViewActivityStatusResource, 'activity_status', full=True, null=True, use_in='detail') websites = fields.ToManyField(WebsiteResource, 'activity_website_set', full=True, null=True, use_in='detail') policy_markers = fields.ToManyField(PolicyMarkerResource, 'policy_marker', full=True, null=True, use_in='detail') collaboration_type = fields.ForeignKey( ActivityViewCollaborationTypeResource, attribute='collaboration_type', full=True, null=True, use_in='detail') default_flow_type = fields.ForeignKey(ActivityViewFlowTypeResource, attribute='default_flow_type', full=True, null=True, use_in='detail') default_finance_type = fields.ForeignKey(FinanceTypeResource, attribute='default_finance_type', full=True, null=True, use_in='detail') default_aid_type = fields.ForeignKey(ActivityViewAidTypeResource, attribute='default_aid_type', full=True, null=True, use_in='detail') default_tied_status = fields.ForeignKey(ActivityViewTiedStatusResource, attribute='default_tied_status', full=True, null=True, use_in='detail') activity_scope = fields.ForeignKey(ActivityViewActivityScopeResource, attribute='scope', full=True, null=True, use_in='detail') default_currency = fields.ForeignKey(ActivityViewCurrencyResource, attribute='default_currency', full=True, null=True, use_in='detail') budget = fields.ToManyField(ActivityBudgetResource, 'budget_set', full=True, null=True, use_in='detail') transactions = fields.ToManyField(ActivityViewTransactionResource, 'transaction_set', full=True, null=True, use_in='detail') documents = fields.ToManyField(DocumentResource, 'documentlink_set', full=True, null=True, use_in='detail') other_identifier = fields.ToManyField(OtherIdentifierResource, 'otheridentifier_set', full=True, null=True, use_in='detail') locations = fields.ToManyField(ActivityLocationResource, 'location_set', full=True, null=True, use_in='all') results = fields.ToManyField(ActivityResultResource, 'results', full=True, null=True, use_in='all') related_activities = fields.ToManyField(RelatedActivityResource, 'related_activities', full=True, null=True, use_in='detail') # to add: # conditions # contact # country-budget? # crsadd # disbursement channel? # ffs # ffs forecast? # planned disbursement # related activity # verification status # vocabulary? class Meta: queryset = Activity.objects.all() resource_name = 'activities' max_limit = 1000 serializer = CsvSerializer() excludes = ['date_created'] ordering = [ 'start_actual', 'start_planned', 'end_actual', 'end_planned', 'sectors', 'total_budget' ] filtering = { 'id': 'in', 'iati_identifier': 'exact', 'start_planned': ALL, 'start_actual': ALL, 'end_planned': ALL, 'end_actual': ALL, 'total_budget': ALL, 'sectors': ('exact', 'in'), 'regions': ('exact', 'in'), 'countries': ('exact', 'in'), 'reporting_organisation': ('exact', 'in'), 'documents': ALL_WITH_RELATIONS, 'results': ALL_WITH_RELATIONS } cache = NoTransformCache() paginator_class = NoCountPaginator def apply_filters(self, request, applicable_filters): activity_list = super(ActivityResource, self).apply_filters( request, applicable_filters).prefetch_related( 'title_set').prefetch_related('description_set') query = request.GET.get('query', None) filter_year_param = request.GET.get('start_year_planned__in', None) if query: search_fields = comma_separated_parameter_to_list( request.GET.get('search_fields', None)) activity_list = activity_list.search(query, search_fields) if filter_year_param: years = comma_separated_parameter_to_list(filter_year_param) activity_list = activity_list.filter_years(years) return activity_list.distinct_if_necessary(applicable_filters) def full_dehydrate(self, bundle, for_list=False): #If the select_fields param is found, run this overwritten method. #Otherwise run the default Tastypie method select_fields_param = bundle.request.GET.get('select_fields', None) if select_fields_param: select_fields = comma_separated_parameter_to_list( select_fields_param) for field_name, field_object in self.fields.items(): #If the field_name is in the list of requested fields dehydrate it if (field_name) in select_fields: # A touch leaky but it makes URI resolution work. if getattr(field_object, 'dehydrated_type', None) == 'related': field_object.api_name = self._meta.api_name field_object.resource_name = self._meta.resource_name bundle.data[field_name] = field_object.dehydrate( bundle, for_list=for_list) # Check for an optional method to do further dehydration. method = getattr(self, "dehydrate_%s" % field_name, None) if method: bundle.data[field_name] = method(bundle) bundle = self.dehydrate(bundle) return bundle else: return super(ActivityResource, self).full_dehydrate(bundle, for_list) def get_list(self, request, **kwargs): # check if call is cached using validator.is_cached # check if call contains flush, if it does the call comes from the cache updater and shouldn't return cached results validator = Validator() cururl = request.META['PATH_INFO'] + "?" + request.META['QUERY_STRING'] if not 'flush' in cururl and validator.is_cached(cururl): return HttpResponse(validator.get_cached_call(cururl), mimetype='application/json') else: return super(ActivityResource, self).get_list(request, **kwargs) def alter_list_data_to_serialize(self, request, data): select_fields_param = request.GET.get('select_fields', None) if select_fields_param: select_fields = comma_separated_parameter_to_list( select_fields_param) data['meta']['selectable_fields'] = { f[0] for f in self.fields.items() } - {f for f in select_fields} return data
class EyeHistoryResource(ModelResource): user = fields.ForeignKey(UserResource, 'user') message = fields.ToManyField(EyeHistoryMessageResource, 'eyehistorymessage_set', null=True, blank=True, full=True) class Meta(BaseMeta): queryset = EyeHistory.objects.select_related().all().order_by( '-start_time') resource_name = 'history-data' list_allowed_methods = ['get', 'post'] detail_allowed_methods = ['get', 'post', 'put', 'delete'] filtering = { 'user': ALL_WITH_RELATIONS, 'url': ALL, 'title': ALL, 'start_time': ALL, 'end_time': ALL, 'total_time': ALL, } paginator_class = Paginator authentication = PublicGetAuthentication() def dehydrate(self, bundle): bundle.data['username'] = bundle.obj.user.username bundle.data['pic_url'] = gravatar_for_user( User.objects.get(username=bundle.obj.user.username)) return bundle.data def obj_create(self, bundle, request=None, **kwargs): url = bundle.data['url'] domain = url_domain(url) bundle.data['domain'] = domain title = bundle.data.get('title') start_time = bundle.data.get('start_time') start_event = bundle.data.get('start_event') end_time = bundle.data.get('end_time') end_event = bundle.data.get('end_event') favicon_url = bundle.data.get('favIconUrl') bundle.data['favicon_url'] = favicon_url src = bundle.data.get('src') tags = bundle.data.get('tags') if tags: tags = json.loads(tags) if end_time and start_time: end_time = datetime.datetime.strptime( end_time, '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=pytz.utc) start_time = datetime.datetime.strptime( start_time, '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=pytz.utc) else: end_time = datetime.datetime.now().replace(tzinfo=pytz.utc) start_time = datetime.datetime.now().replace(tzinfo=pytz.utc) message = bundle.data.get('message') highlight = bundle.data.get('highlight') parent_comment = bundle.data.get('parent_comment') if message and message.strip() == '': message = None if message: bundle.data.pop('message', None) if highlight: bundle.data.pop('highlight', None) if parent_comment: bundle.data.pop('parent_comment', None) try: exists = EyeHistory.objects.filter(user=request.user, url=url, title=title, src=src, favicon_url=favicon_url, start_time__gt=start_time - datetime.timedelta(minutes=1), start_event=start_event) if exists.count() > 0: eye_his = exists[0] eye_his.end_time = end_time eye_his.end_event = end_event elapsed_time = end_time - start_time eye_his.total_time = int( round((elapsed_time.microseconds / 1.0E3) + (elapsed_time.seconds * 1000) + (elapsed_time.days * 8.64E7))) eye_his.humanize_time = humanize_time(elapsed_time) eye_his.save() if message: eye_message, _ = EyeHistoryMessage.objects.get_or_create( eyehistory=eye_his, message=message) notify_message(message=eye_message) else: # save_raw_eyehistory(request.user, url, title, start_event, end_event, start_time, end_time, src, domain, favicon_url) dup_histories = EyeHistory.objects.filter( user=request.user, url=url, title=title, end_time__gt=start_time - datetime.timedelta(minutes=5)) if dup_histories.count() > 0: obj = merge_histories(dup_histories, end_time, end_event) if message: eye_message, _ = EyeHistoryMessage.objects.get_or_create( eyehistory=obj, message=message) notify_message(message=eye_message) else: bundle_res = super(EyeHistoryResource, self).obj_create(bundle, request, user=request.user, **kwargs) check_bumps(request.user, start_time, end_time, url) if message: eye_message = None if parent_comment: h = Highlight.objects.get(id=highlight) eye_message, _ = EyeHistoryMessage.objects.get_or_create( eyehistory=bundle_res.obj, message=message, highlight=h, parent_comment=parent_comment) elif highlight: h = Highlight.objects.get(id=highlight) eye_message, _ = EyeHistoryMessage.objects.get_or_create( eyehistory=bundle_res.obj, message=message, highlight=h) else: eye_message, _ = EyeHistoryMessage.objects.get_or_create( eyehistory=bundle_res.obj, message=message) if tags: for tag in tags: if len( Tag.objects.filter( comment=eye_message, common_tag__name=tag)) == 0: try: common_tag = CommonTag.objects.get( name=tag) vt = Tag( common_tag=common_tag, user=request.user, comment=eye_message, ) vt.save() except CommonTag.DoesNotExist: pass notify_message(message=eye_message) return bundle_res except MultipleObjectsReturned as e: logger.info(e) # multiple items created, delete duplicates call_command('remove_duplicate_history') return bundle
class MovieResource(ModelResource): actor = fields.ForeignKey(ActorResource, 'actor') class Meta: queryset = Movie.objects.all() resource_name = 'movie'
class AppMakerResource(GCloudModelResource): business = fields.ForeignKey(BusinessResource, 'business', full=True) creator_name = fields.CharField(attribute='creator_name', readonly=True, null=True) editor_name = fields.CharField(attribute='editor_name', readonly=True, null=True) template_scheme_id = fields.CharField(attribute='template_scheme_id', readonly=True, blank=True) task_template = fields.ForeignKey( TaskTemplateResource, 'task_template', ) template_id = fields.CharField(attribute='task_template_id', readonly=True, null=True) template_name = fields.CharField(attribute='task_template_name', readonly=True, null=True) category = fields.CharField(attribute='category', readonly=True, null=True) class Meta: queryset = AppMaker.objects.filter(is_deleted=False) resource_name = 'appmaker' excludes = [] authorization = GCloudGenericAuthorization() always_return_data = True serializer = AppSerializer() filtering = { "business": ALL_WITH_RELATIONS, "template": ALL_WITH_RELATIONS, "name": ALL, "creator": ALL, "editor": ALL, 'create_time': ['gte', 'lte'], 'edit_time': ['gte', 'lte'], } limit = 0 def obj_delete(self, bundle, **kwargs): try: appmaker_id = kwargs['pk'] appmaker = AppMaker.objects.get(pk=appmaker_id) except Exception: raise BadRequest('appmaker[id=%s] does not exist' % appmaker_id) biz_cc_id = appmaker.business.cc_id business = get_business_for_user(bundle.request.user, ['manage_business']) if not business.filter(cc_id=biz_cc_id).exists(): raise ImmediateHttpResponse( HttpResponseForbidden( 'you have no permissions to delete appmaker')) if settings.IS_LOCAL: fake = True else: fake = False result, data = AppMaker.objects.del_app_maker(biz_cc_id, appmaker_id, fake) if not result: raise BadRequest(data)
class LayerResource(CommonModelApi): """Layer API""" links = fields.ListField(attribute='links', null=True, use_in='all', default=[]) if check_ogc_backend(qgis_server.BACKEND_PACKAGE): default_style = fields.ForeignKey('geonode.api.api.StyleResource', attribute='qgis_default_style', null=True) styles = fields.ManyToManyField('geonode.api.api.StyleResource', attribute='qgis_styles', null=True, use_in='detail') elif check_ogc_backend(geoserver.BACKEND_PACKAGE): default_style = fields.ForeignKey('geonode.api.api.StyleResource', attribute='default_style', null=True) styles = fields.ManyToManyField('geonode.api.api.StyleResource', attribute='styles', null=True, use_in='detail') def format_objects(self, objects): """ Formats the object. """ formatted_objects = [] for obj in objects: # convert the object to a dict using the standard values. # includes other values values = self.VALUES + ['alternate', 'name'] formatted_obj = model_to_dict(obj, fields=values) username = obj.owner.get_username() full_name = (obj.owner.get_full_name() or username) formatted_obj['owner__username'] = username formatted_obj['owner_name'] = full_name if obj.category: formatted_obj[ 'category__gn_description'] = obj.category.gn_description if obj.group: formatted_obj['group'] = obj.group try: formatted_obj['group_name'] = GroupProfile.objects.get( slug=obj.group.name) except GroupProfile.DoesNotExist: formatted_obj['group_name'] = obj.group formatted_obj['keywords'] = [k.name for k in obj.keywords.all() ] if obj.keywords else [] # embrapa # #formatted_obj['embrapa_keywords'] = [ek.name for ek in obj.embrapa_keywords.all()] if objects.embrapa_keywords else [] formatted_obj['regions'] = [r.name for r in obj.regions.all() ] if obj.regions else [] # provide style information bundle = self.build_bundle(obj=obj) formatted_obj['default_style'] = self.default_style.dehydrate( bundle, for_list=True) # Add resource uri formatted_obj['resource_uri'] = self.get_resource_uri(bundle) formatted_obj['links'] = self.dehydrate_ogc_links(bundle) if 'site_url' not in formatted_obj or len( formatted_obj['site_url']) == 0: formatted_obj['site_url'] = settings.SITEURL # Probe Remote Services formatted_obj['store_type'] = 'dataset' formatted_obj['online'] = True if hasattr(obj, 'storeType'): formatted_obj['store_type'] = obj.storeType if obj.storeType == 'remoteStore' and hasattr( obj, 'remote_service'): if obj.remote_service: formatted_obj['online'] = ( obj.remote_service.probe == 200) else: formatted_obj['online'] = False formatted_obj['gtype'] = self.dehydrate_gtype(bundle) # replace thumbnail_url with curated_thumbs if hasattr(obj, 'curatedthumbnail'): formatted_obj[ 'thumbnail_url'] = obj.curatedthumbnail.thumbnail_url # put the object on the response stack formatted_objects.append(formatted_obj) return formatted_objects def _dehydrate_links(self, bundle, link_types=None): """Dehydrate links field.""" dehydrated = [] obj = bundle.obj link_fields = ['extension', 'link_type', 'name', 'mime', 'url'] links = obj.link_set.all() if link_types: links = links.filter(link_type__in=link_types) for l in links: formatted_link = model_to_dict(l, fields=link_fields) dehydrated.append(formatted_link) return dehydrated def dehydrate_links(self, bundle): return self._dehydrate_links(bundle) def dehydrate_ogc_links(self, bundle): return self._dehydrate_links(bundle, ['OGC:WMS', 'OGC:WFS', 'OGC:WCS']) def dehydrate_gtype(self, bundle): return bundle.obj.gtype def populate_object(self, obj): """Populate results with necessary fields :param obj: Layer obj :type obj: Layer :return: """ if check_ogc_backend(qgis_server.BACKEND_PACKAGE): # Provides custom links for QGIS Server styles info # Default style try: obj.qgis_default_style = obj.qgis_layer.default_style except Exception: obj.qgis_default_style = None # Styles try: obj.qgis_styles = obj.qgis_layer.styles except Exception: obj.qgis_styles = [] return obj def build_bundle(self, obj=None, data=None, request=None, **kwargs): """Override build_bundle method to add additional info.""" if obj is None and self._meta.object_class: obj = self._meta.object_class() elif obj: obj = self.populate_object(obj) return Bundle(obj=obj, data=data, request=request, **kwargs) def patch_detail(self, request, **kwargs): """Allow patch request to update default_style. Request body must match this: { 'default_style': <resource_uri_to_style> } """ reason = 'Can only patch "default_style" field.' try: body = json.loads(request.body) if 'default_style' not in body: return http.HttpBadRequest(reason=reason) match = resolve(body['default_style']) style_id = match.kwargs['id'] api_name = match.kwargs['api_name'] resource_name = match.kwargs['resource_name'] if not (resource_name == 'styles' and api_name == 'api'): raise Exception() from geonode.qgis_server.models import QGISServerStyle style = QGISServerStyle.objects.get(id=style_id) layer_id = kwargs['id'] layer = Layer.objects.get(id=layer_id) except Exception: return http.HttpBadRequest(reason=reason) from geonode.qgis_server.views import default_qml_style request.method = 'POST' response = default_qml_style(request, layername=layer.name, style_name=style.name) if isinstance(response, TemplateResponse): if response.status_code == 200: return HttpResponse(status=200) return self.error_response(request, response.content) # copy parent attribute before modifying VALUES = CommonModelApi.VALUES[:] VALUES.append('typename') class Meta(CommonMetaApi): paginator_class = CrossSiteXHRPaginator queryset = Layer.objects.distinct().order_by('-date') resource_name = 'layers' detail_uri_name = 'id' include_resource_uri = True allowed_methods = ['get', 'patch'] excludes = ['csw_anytext', 'metadata_xml'] authentication = MultiAuthentication(SessionAuthentication(), OAuthAuthentication(), GeonodeApiKeyAuthentication()) filtering = CommonMetaApi.filtering # Allow filtering using ID filtering.update({ 'id': ALL, 'name': ALL, 'alternate': ALL, })
class TaskResource(ModelResource): # people = fields.ToManyField(InternalUserProfileResource, 'people', full=True, null=True) user = fields.ForeignKey(InternalUserProfileResource, 'user', full=True, null=False) total_records = fields.CharField(attribute='total_records', default=0, readonly=True) class Meta(object): queryset = Task.objects \ .all() \ .select_related() \ .prefetch_related('user') resource_name = 'tasks' filtering = {'title': ALL, 'id': ALL} authentication = ApiKeyAuthenticationExt() authorization = UserObjectsOnlyAuthorization() always_return_data = True paginator_class = PageNumberPaginator include_resource_uri = False def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/listing%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_tasks'), name="api_get_tasks") ] def validation(self, bundle): if bundle.request.method == 'POST': if bundle.data.get('title', '') == '' \ or bundle.data.get('select_date', '') == '' \ or bundle.data.get('select_time', '') == '': raise CustomBadRequest(error_type='INVALID_OPERATOR', error_message="Cant create the task") def validate_duplicate(self, bundle): title = bundle.data['title'] date = bundle.data['select_date'] time = bundle.data['select_time'] if title and date and time: if Task.objects.filter(title__iexact=title, select_time__iexact=time, select_date__iexact=date).exists(): raise CustomBadRequest( error_type='DUPLICATE_TASK', error_message="A same task is already in your list") def hydrate(self, bundle): # Always tie task to the current user profile if bundle.request.method == 'POST': bundle.data["user"] = bundle.request.user.userprofile rq_date = bundle.data["select_date"] bundle.data["task_date"] = convert_to_date(rq_date) return super(TaskResource, self).hydrate(bundle) def dehydrate(self, bundle): if "user" in bundle.data: bundle.data.pop("user", None) if "total_records" in bundle.data: bundle.data.pop('total_records', None) if 'task_date' in bundle.data: bundle.data.pop('task_date', None) return super(TaskResource, self).dehydrate(bundle) def build_filters(self, filters=None): if filters is None: filters = {} q = None if 'q' in filters: q = filters.pop('q') orm_filters = super(TaskResource, self).build_filters(filters) if q: orm_filters['q'] = q return orm_filters def apply_filters(self, request, applicable_filters): if 'q' in applicable_filters: q = applicable_filters.pop('q') else: q = None semi_filtered = super(TaskResource, self).apply_filters(request, applicable_filters) # Always get task belong to an user semi_filtered = semi_filtered.filter( user_id=request.user.userprofile.id, is_deleted=False) # Just only get tasks that has date is greater than the current dates q_date = request.GET.get('date', None) if q_date is None: current_date = get_current_date() else: current_date = convert_to_date(q_date) semi_filtered = semi_filtered.filter(task_date=current_date) if q: semi_filtered = semi_filtered.search(q[0], raw=True, fields=('title', )) return semi_filtered def obj_get(self, bundle, **kwargs): return super(TaskResource, self).obj_get(bundle, **kwargs) def obj_create(self, bundle, **kwargs): self.validation(bundle) # self.validate_duplicate(bundle) try: return super(TaskResource, self).obj_create(bundle, **kwargs) except Exception as e: raise CustomBadRequest(error_type='UNKNOWNERROR', error_message=str(e)) # def save_m2m(self, bundle): # people = bundle.data['people'] # for user in people: # user.data['user'] = bundle.obj # # return super(TaskResource, self).save_m2m(bundle) def get_tasks(self, request, **kwargs): self.is_authenticated(request) self.method_check(request, allowed=['get']) self.throttle_check(request) self.log_throttled_access(request) return self.get_list(request)
class IPReadingResource(ModelResource): ipseries = fields.ForeignKey(IPSeriesResource, 'ipseries') class Meta: queryset = IPReading.objects.all() resource_name = 'ipreading' ordering = ['timestamp', 'id', 'pk']
class TempReadingResource(ModelResource): tempseries = fields.ForeignKey(TempSeriesResource, 'tempseries') class Meta: queryset = TempReading.objects.all() resource_name = 'tempreading' ordering = ['timestamp', 'id', 'pk']
class DirectorResource(ModelResource): probe = fields.ForeignKey(ProbeResource, 'probe', full=True) time_profile = fields.ForeignKey(TimeProfileResource, 'time_profile', full=True) backends = fields.ToManyField('vaas.manager.api.BackendResource', 'backends', null=True) cluster = fields.ToManyField('vaas.cluster.api.LogicalClusterResource', 'cluster', null=False, full=True) class Meta: queryset = Director.objects.all() resource_name = 'director' serializer = PrettyJSONSerializer() authorization = DjangoAuthorization() authentication = VaasMultiAuthentication(ApiKeyAuthentication(), SessionAuthentication()) validation = ModelCleanedDataFormValidation( form_class=DirectorModelForm) always_return_data = True filtering = { 'name': ['exact'], 'enabled': ['exact'], 'probe': ALL_WITH_RELATIONS, 'cluster': ALL_WITH_RELATIONS, 'service': ['exact'] } def save_m2m(self, bundle): try: new_uris = bundle.obj.new_clusters_uris bundle.obj.new_clusters = [ cluster.obj for cluster in bundle.data['cluster'] if cluster.data['resource_uri'] in new_uris ] logger.info("[DirectorResource.save_m2m()] new_clusters = %s", bundle.obj.new_clusters) except (AttributeError, KeyError): pass return super(DirectorResource, self).save_m2m(bundle) def update_in_place(self, request, original_bundle, new_data): try: original_bundle.obj.old_clusters = list( original_bundle.obj.cluster.all()) except AttributeError: original_bundle.obj.old_clusters = [] logger.info("[DirectorResource.update_in_place()] old_clusters = %s", original_bundle.obj.old_clusters) try: original_bundle.obj.new_clusters_uris = new_data['cluster'] except KeyError: original_bundle.obj.new_clusters_uris = [] original_bundle.obj.new_data = new_data return super(DirectorResource, self).update_in_place(request, original_bundle, new_data)
class VersionResource(ModelResource): project = fields.ForeignKey(ProjectResource, 'project', full=True) class Meta(object): allowed_methods = ['get', 'put', 'post'] always_return_data = True queryset = Version.objects.api() authentication = PostAuthentication() authorization = DjangoAuthorization() filtering = { "project": ALL_WITH_RELATIONS, "slug": ALL_WITH_RELATIONS, "active": ALL, } # Find a better name for this before including it. # def dehydrate(self, bundle): # bundle.data['subdomain'] = "http://%s/en/%s/" % ( # bundle.obj.project.subdomain, bundle.obj.slug # ) # return bundle def get_object_list(self, request): self._meta.queryset = Version.objects.api(user=request.user, only_active=False) return super(VersionResource, self).get_object_list(request) def version_compare(self, request, project_slug, base=None, **kwargs): project = get_object_or_404(Project, slug=project_slug) if base and base != LATEST: try: base_version = project.versions.get(slug=base) except (Version.DoesNotExist, TypeError): base_version = None else: base_version = None ret_val = get_version_compare_data(project, base_version) return self.create_response(request, ret_val) def build_version(self, request, **kwargs): project = get_object_or_404(Project, slug=kwargs['project_slug']) version = kwargs.get('version_slug', LATEST) version_obj = project.versions.get(slug=version) trigger_build(project=project, version=version_obj) return self.create_response(request, {'building': True}) def override_urls(self): return [ url(r"^(?P<resource_name>%s)/schema/$" % self._meta.resource_name, self.wrap_view('get_schema'), name="api_get_schema"), url((r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/highest/" r"(?P<base>.+)/$") % self._meta.resource_name, self.wrap_view('version_compare'), name="version_compare"), url(r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/highest/$" % self._meta.resource_name, self.wrap_view('version_compare'), name="version_compare"), url( r"^(?P<resource_name>%s)/(?P<project__slug>[a-z-_]+[a-z0-9-_]+)/$" # noqa % self._meta.resource_name, self.wrap_view('dispatch_list'), name="api_version_list"), url((r"^(?P<resource_name>%s)/(?P<project_slug>[a-z-_]+)/(?P" r"<version_slug>[a-z0-9-_.]+)/build/$") % self._meta.resource_name, self.wrap_view('build_version'), name="api_version_build_slug"), ]
class GroupResource(SlimGroupResource): owner = fields.ForeignKey(SlimProfileResource, 'owner') students = fields.ToManyField(SlimProfileResource, 'students', full=True) class Meta(SlimGroupResource.Meta): queryset = SlimGroupResource.Meta.queryset.prefetch_related( 'students__user').select_related('owner__user') fields = SlimGroupResource.Meta.fields + ['owner', 'students'] def _group_unread_counts(self, groups, request, profile): # This is called when the group queryset is evaluated; we attach an # `all_students_group` to the request, and send it along for the # unread-counts-fetching along with the other groups. request.all_students_group = model.AllStudentsGroup(profile) all_groups = [request.all_students_group] + list(groups) counts = super(GroupResource, self)._group_unread_counts(all_groups, request, profile) request.all_students_group.unread_count = counts.pop( request.all_students_group) return counts def full_dehydrate(self, bundle): """Special handling for all-students group.""" if bundle.obj.is_all: profile_resource = SlimProfileResource() def dehydrate_student(student): b = profile_resource.build_bundle(obj=student, request=bundle.request) return profile_resource.full_dehydrate(b) bundle.data.update({ 'id': bundle.obj.id, 'name': bundle.obj.name, 'students_uri': reverse( 'api_dispatch_list', kwargs={ 'resource_name': 'user', 'api_name': 'v1' }, ) + '?elders=%s' % bundle.obj.owner.id, 'group_uri': reverse('all_students_dash'), 'add_student_uri': reverse('add_student'), 'owner': reverse( 'api_dispatch_detail', kwargs={ 'resource_name': 'user', 'api_name': 'v1', 'pk': bundle.obj.owner.id, }, ), 'unread_count': bundle.obj.unread_count, 'students': [dehydrate_student(s) for s in bundle.obj.owner.students], }) else: bundle = super(GroupResource, self).full_dehydrate(bundle) return bundle def obj_get_list(self, request=None, **kwargs): qs = super(GroupResource, self).obj_get_list(request, **kwargs) # Evaluate the group queryset (populates request.all_students_group) groups = list(qs) if request is not None: # pragma: no cover # Actually add the all-students-group to the list of groups groups.insert(0, request.all_students_group) return groups
class ProjectResource(ModelResource): author = fields.ForeignKey(UserResource, 'author', full=True) date_fmt = "%m/%d/%y %I:%M %p" def __init__(self, *args, **kwargs): # @todo: extras is a side-effect of the Mustache templating system # not supporting the ability to reference variables in the parent # context. ideally, the templating system should be switched out to # something more reasonable self.editable = kwargs.pop('editable', {}) self.record_viewer = kwargs.pop('record_viewer', {}) self.is_viewer_faculty = kwargs.pop('is_viewer_faculty', False) self.extras = kwargs.pop('extras', {}) super(ProjectResource, self).__init__(*args, **kwargs) class Meta: queryset = Project.objects.all().order_by('id') excludes = [ 'participants', 'body', 'submitted', 'feedback', 'sherdnote_set' ] list_allowed_methods = [] detail_allowed_methods = [] authentication = ClassLevelAuthentication() ordering = ['id', 'title'] def dehydrate(self, bundle): bundle.data['is_assignment'] = \ bundle.obj.visibility_short() == 'Assignment' bundle.data['is_response'] = bundle.obj.assignment() is not None bundle.data['attribution'] = bundle.obj.attribution() bundle.data['url'] = bundle.obj.get_absolute_url() bundle.data['due_date'] = bundle.obj.get_due_date() bundle.data['modified_date'] = bundle.obj.modified.strftime("%m/%d/%y") bundle.data['modified_time'] = bundle.obj.modified.strftime("%I:%M %p") bundle.data['editable'] = self.editable bundle.data['is_faculty'] = self.is_viewer_faculty participants = bundle.obj.attribution_list() bundle.data['participants'] = [{ 'name': p.get_full_name(), 'username': p.username, 'public_name': get_public_name(p, bundle.request), 'is_viewer': self.record_viewer == p.username, 'last': idx == (len(participants) - 1) } for idx, p in enumerate(participants)] bundle.data['status'] = bundle.obj.status() for key, value in self.extras.items(): bundle.data[key] = value return bundle def render_one(self, request, project, version_number=None): bundle = self.build_bundle(obj=project, request=request) dehydrated = self.full_dehydrate(bundle) project_ctx = self._meta.serializer.to_simple(dehydrated, None) project_ctx['body'] = project.body project_ctx['public_url'] = project.public_url() project_ctx['current_version'] = version_number project_ctx['visibility'] = project.visibility_short() project_ctx['type'] = ('assignment' if project.is_assignment(request) else 'composition') rand = ''.join([choice(letters) for i in range(5)]) asset_resource = AssetResource() sherd_resource = SherdNoteResource() assets = {} notes = [] for note in project.citations(): notes.append(sherd_resource.render_one(request, note, rand)) if (note.title not in ["Annotation Deleted", 'Asset Deleted']): key = '%s_%s' % (rand, note.asset.pk) if key not in assets.keys(): assets[key] = \ asset_resource.render_one(request, note.asset) data = { 'project': project_ctx, 'type': 'project', 'can_edit': self.editable, 'annotations': notes, 'assets': assets } data['responses'] = [] for response in project.responses(request): if response.can_read(request): obj = { 'url': response.get_absolute_url(), 'title': response.title, 'modified': response.modified.strftime(self.date_fmt), 'attribution_list': [] } last = len(response.attribution_list()) - 1 for idx, author in enumerate(response.attribution_list()): obj['attribution_list'].append({ 'name': get_public_name(author, request), 'last': idx == last }) data['responses'].append(obj) data['response_count'] = len(data['responses']) my_responses = [] for response in project.responses_by(request, request.user): obj = { 'url': response.get_absolute_url(), 'title': response.title, 'modified': response.modified.strftime(self.date_fmt), 'attribution_list': [] } last = len(response.attribution_list()) - 1 for idx, author in enumerate(response.attribution_list()): obj['attribution_list'].append({ 'name': get_public_name(author, request), 'last': idx == last }) my_responses.append(obj) if len(my_responses) == 1: data['my_response'] = my_responses[0] elif len(my_responses) > 1: data['my_responses'] = my_responses data['my_responses_count'] = len(my_responses) if project.is_participant(request.user): data['revisions'] = [{ 'version_number': v.version_number, 'versioned_id': v.versioned_id, 'author': get_public_name(v.instance().author, request), 'modified': v.modified.strftime("%m/%d/%y %I:%M %p") } for v in project.versions.order_by('-change_time')] if self.editable: projectform = ProjectForm(request, instance=project) data['form'] = { 'participants': projectform['participants'].__unicode__(), 'publish': projectform['publish'].__unicode__() } return data def render_assignments(self, request, assignments): lst = [] for a in assignments: bundle = self.build_bundle(obj=a, request=request) dehydrated = self.full_dehydrate(bundle) ctx = self._meta.serializer.to_simple(dehydrated, None) ctx['display_as_assignment'] = True lst.append(ctx) return lst def render_projects(self, request, projects): lst = [] for project in projects: abundle = self.build_bundle(obj=project, request=request) dehydrated = self.full_dehydrate(abundle) ctx = self._meta.serializer.to_simple(dehydrated, None) if self.editable: feedback = project.feedback_discussion() if feedback: ctx['feedback'] = feedback.id parent_assignment = project.assignment() if parent_assignment: ctx['collaboration'] = {} ctx['collaboration']['title'] = parent_assignment.title ctx['collaboration']['url'] = \ parent_assignment.get_absolute_url() ctx['collaboration']['due_date'] = \ parent_assignment.get_due_date() is_assignment = project.is_assignment(request) if is_assignment: count = 0 for response in project.responses(request): if response.can_read(request): count += 1 ctx['responses'] = count ctx['is_assignment'] = True ctx['responses'] = len(project.responses(request)) ctx['display_as_assignment'] = \ is_assignment or parent_assignment is not None lst.append(ctx) return lst def render_list(self, request, projects): lst = [] for project in projects.all(): bundle = self.build_bundle(obj=project, request=request) dehydrated = self.full_dehydrate(bundle) ctx = self._meta.serializer.to_simple(dehydrated, None) lst.append(ctx) return sorted(lst, key=lambda item: item['title'])
class QGISStyleResource(ModelResource): """Styles API for QGIS Server backend.""" body = fields.CharField(attribute='body', use_in='detail') name = fields.CharField(attribute='name') title = fields.CharField(attribute='title') layer = fields.ForeignKey('geonode.api.resourcebase_api.LayerResource', attribute='layer', null=True) style_url = fields.CharField(attribute='style_url') type = fields.CharField(attribute='type') class Meta: paginator_class = CrossSiteXHRPaginator queryset = QGISServerStyle.objects.all() resource_name = 'styles' detail_uri_name = 'id' allowed_methods = ['get', 'post', 'delete'] authorization = GeoNodeStyleAuthorization() filtering = { 'id': ALL, 'title': ALL, 'name': ALL, 'layer': ALL_WITH_RELATIONS } def populate_object(self, style): """Populate results with necessary fields :param style: Style objects :type style: QGISServerStyle :return: """ try: qgis_layer = style.layer_styles.first() """:type: geonode.qgis_server.QGISServerLayer""" style.layer = qgis_layer.layer style.type = 'qml' except Exception: pass return style def build_filters(self, filters=None, **kwargs): """Apply custom filters for layer.""" filters = super(QGISStyleResource, self).build_filters(filters, **kwargs) # Convert layer__ filters into layer_styles__layer__ updated_filters = {} for key, value in filters.items(): key = key.replace('layer__', 'layer_styles__layer__') updated_filters[key] = value return updated_filters def build_bundle(self, obj=None, data=None, request=None, **kwargs): """Override build_bundle method to add additional info.""" if obj is None and self._meta.object_class: obj = self._meta.object_class() elif obj: obj = self.populate_object(obj) return Bundle(obj=obj, data=data, request=request, **kwargs) def post_list(self, request, **kwargs): """Attempt to redirect to QGIS Server Style management. A post method should have the following field: name: Slug name of style title: Title of style style: the style file uploaded Also, should have kwargs: layername or layer__name: The layer name associated with the style or layer__id: The layer id associated with the style """ from geonode.qgis_server.views import qml_style # Extract layer name information POST = request.POST FILES = request.FILES layername = POST.get('layername') or POST.get('layer__name') if not layername: layer_id = POST.get('layer__id') layer = Layer.objects.get(id=layer_id) layername = layer.name # move style file FILES['qml'] = FILES['style'] response = qml_style(request, layername) if isinstance(response, TemplateResponse): if response.status_code == 201: obj = QGISServerStyle.objects.get( layer_styles__layer__name=layername, name=POST['name']) updated_bundle = self.build_bundle(obj=obj, request=request) 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) else: context = response.context_data # Check form valid style_upload_form = context['style_upload_form'] if not style_upload_form.is_valid(): raise BadRequest(style_upload_form.errors.as_text()) alert_message = context['alert_message'] raise BadRequest(alert_message) elif isinstance(response, HttpResponse): response_class = None if response.status_code == 403: response_class = http.HttpForbidden return self.error_response(request, response.content, response_class=response_class) def delete_detail(self, request, **kwargs): """Attempt to redirect to QGIS Server Style management.""" from geonode.qgis_server.views import qml_style style_id = kwargs.get('id') qgis_style = QGISServerStyle.objects.get(id=style_id) layername = qgis_style.layer_styles.first().layer.name response = qml_style(request, layername, style_name=qgis_style.name) if isinstance(response, TemplateResponse): if response.status_code == 200: # style deleted return http.HttpNoContent() else: context = response.context_data # Check form valid style_upload_form = context['style_upload_form'] if not style_upload_form.is_valid(): raise BadRequest(style_upload_form.errors.as_text()) alert_message = context['alert_message'] raise BadRequest(alert_message) elif isinstance(response, HttpResponse): response_class = None if response.status_code == 403: response_class = http.HttpForbidden return self.error_response(request, response.content, response_class=response_class) def delete_list(self, request, **kwargs): """Do not allow delete list""" return http.HttpForbidden()
class TaskResource(ModelResource): project = fields.ForeignKey('project.apps.base.api.ProjectResource', 'project') version = fields.ForeignKey('project.apps.base.api.VersionResource', 'version', null=True, blank=True) author = fields.ForeignKey(UserResource, 'author') assigned_to = fields.ForeignKey(UserResource, 'assigned_to', null=True, blank=True) class Meta: queryset = RedTask.objects.all() resource_name = 'task' filtering = { 'project': ALL_WITH_RELATIONS, 'version': ALL_WITH_RELATIONS, 'author': ALL_WITH_RELATIONS, 'assigned_to': ALL_WITH_RELATIONS, } include_resource_uri = False # cache = SimpleCache(timeout=10) authentication = BasicAuthentication() def get_object_list(self, request): projects = [] if request.user.is_superuser: user_perm = False else: try: user_perm = request.user.reduser rolesets = RedRoleSet.objects.filter(users=user_perm) for role in rolesets: projects.append(role.project) except RedUser.DoesNotExist: user_perm = False if user_perm: tasks = RedTask.objects.filter(project__in=projects) else: tasks = RedTask.objects.all() return tasks def dehydrate_project(self, bundle): return bundle.obj.project.id def dehydrate_version(self, bundle): if bundle.obj.version: return bundle.obj.version.id else: return None def dehydrate_author(self, bundle): return bundle.obj.author.id def dehydrate_assigned_to(self, bundle): if bundle.obj.assigned_to: return bundle.obj.assigned_to.id else: return None
class ExperimentParameterResource(ParameterResource): parameterset = fields.ForeignKey(ExperimentParameterSetResource, 'parameterset') class Meta(ParameterResource.Meta): queryset = ExperimentParameter.objects.all()
class LayerResource(CommonModelApi): """Layer API""" links = fields.ListField( attribute='links', null=True, use_in='all', default=[]) if check_ogc_backend(geoserver.BACKEND_PACKAGE): default_style = fields.ForeignKey( 'geonode.api.api.StyleResource', attribute='default_style', null=True) styles = fields.ManyToManyField( 'geonode.api.api.StyleResource', attribute='styles', null=True, use_in='detail') def format_objects(self, objects): """ Formats the object. """ formatted_objects = [] for obj in objects: # convert the object to a dict using the standard values. # includes other values values = self.VALUES + [ 'alternate', 'name' ] formatted_obj = model_to_dict(obj, fields=values) username = obj.owner.get_username() full_name = (obj.owner.get_full_name() or username) formatted_obj['owner__username'] = username formatted_obj['owner_name'] = full_name if obj.category: formatted_obj['category__gn_description'] = _(obj.category.gn_description) if obj.group: formatted_obj['group'] = obj.group try: formatted_obj['group_name'] = GroupProfile.objects.get(slug=obj.group.name) except GroupProfile.DoesNotExist: formatted_obj['group_name'] = obj.group formatted_obj['keywords'] = [k.name for k in obj.keywords.all()] if obj.keywords else [] formatted_obj['regions'] = [r.name for r in obj.regions.all()] if obj.regions else [] # provide style information bundle = self.build_bundle(obj=obj) formatted_obj['default_style'] = self.default_style.dehydrate( bundle, for_list=True) # Add resource uri formatted_obj['resource_uri'] = self.get_resource_uri(bundle) formatted_obj['links'] = self.dehydrate_ogc_links(bundle) if 'site_url' not in formatted_obj or len(formatted_obj['site_url']) == 0: formatted_obj['site_url'] = settings.SITEURL # Probe Remote Services formatted_obj['store_type'] = 'dataset' formatted_obj['online'] = True if hasattr(obj, 'storeType'): formatted_obj['store_type'] = obj.storeType if obj.storeType == 'remoteStore' and hasattr(obj, 'remote_service'): if obj.remote_service: formatted_obj['online'] = (obj.remote_service.probe == 200) else: formatted_obj['online'] = False formatted_obj['gtype'] = self.dehydrate_gtype(bundle) # replace thumbnail_url with curated_thumbs if hasattr(obj, 'curatedthumbnail'): formatted_obj['thumbnail_url'] = obj.curatedthumbnail.thumbnail_url formatted_obj['processed'] = obj.instance_is_processed # put the object on the response stack formatted_objects.append(formatted_obj) return formatted_objects def _dehydrate_links(self, bundle, link_types=None): """Dehydrate links field.""" dehydrated = [] obj = bundle.obj link_fields = [ 'extension', 'link_type', 'name', 'mime', 'url' ] links = obj.link_set.all() if link_types: links = links.filter(link_type__in=link_types) for lnk in links: formatted_link = model_to_dict(lnk, fields=link_fields) dehydrated.append(formatted_link) return dehydrated def dehydrate_links(self, bundle): return self._dehydrate_links(bundle) def dehydrate_ogc_links(self, bundle): return self._dehydrate_links(bundle, ['OGC:WMS', 'OGC:WFS', 'OGC:WCS']) def dehydrate_gtype(self, bundle): return bundle.obj.gtype def build_bundle( self, obj=None, data=None, request=None, **kwargs): """Override build_bundle method to add additional info.""" if obj is None and self._meta.object_class: obj = self._meta.object_class() elif obj: obj = self.populate_object(obj) return Bundle( obj=obj, data=data, request=request, **kwargs) def populate_object(self, obj): """Populate results with necessary fields :param obj: Layer obj :type obj: Layer :return: """ return obj # copy parent attribute before modifying VALUES = CommonModelApi.VALUES[:] VALUES.append('typename') class Meta(CommonMetaApi): paginator_class = CrossSiteXHRPaginator queryset = Layer.objects.distinct().order_by('-date') resource_name = 'layers' detail_uri_name = 'id' include_resource_uri = True allowed_methods = ['get', 'patch'] excludes = ['csw_anytext', 'metadata_xml'] authentication = MultiAuthentication(SessionAuthentication(), OAuthAuthentication(), GeonodeApiKeyAuthentication()) filtering = CommonMetaApi.filtering # Allow filtering using ID filtering.update({ 'id': ALL, 'name': ALL, 'alternate': ALL, })
class ExperimentResource(MyTardisModelResource): '''API for Experiments also creates a default ACL and allows ExperimentParameterSets to be read and written. TODO: catch duplicate schema submissions for parameter sets ''' created_by = fields.ForeignKey(UserResource, 'created_by') parameter_sets = fields.ToManyField( 'tardis.tardis_portal.api.ExperimentParameterSetResource', 'experimentparameterset_set', related_name='experiment', full=True, null=True) class Meta(MyTardisModelResource.Meta): queryset = Experiment.objects.all() filtering = { 'id': ('exact', ), 'title': ('exact', ), } ordering = ['id', 'title', 'created_time', 'update_time'] always_return_data = True def dehydrate(self, bundle): exp = bundle.obj authors = [{ 'name': a.author, 'url': a.url } for a in exp.experimentauthor_set.all()] bundle.data['authors'] = authors lic = exp.license if lic is not None: bundle.data['license'] = { 'name': lic.name, 'url': lic.url, 'description': lic.internal_description, 'image_url': lic.image_url, 'allows_distribution': lic.allows_distribution, } owners = exp.get_owners() bundle.data['owner_ids'] = [o.id for o in owners] return bundle def hydrate_m2m(self, bundle): ''' create ACL before any related objects are created in order to use ACL permissions for those objects. ''' if getattr(bundle.obj, 'id', False): experiment = bundle.obj # TODO: unify this with the view function's ACL creation, # maybe through an ACL toolbox. acl = ObjectACL(content_type=experiment.get_ct(), object_id=experiment.id, pluginId=django_user, entityId=str(bundle.request.user.id), canRead=True, canWrite=True, canDelete=True, isOwner=True, aclOwnershipType=ObjectACL.OWNER_OWNED) acl.save() return super(ExperimentResource, self).hydrate_m2m(bundle) def obj_create(self, bundle, **kwargs): '''experiments need at least one ACL to be available through the ExperimentManager (Experiment.safe) Currently not tested for failed db transactions as sqlite does not enforce limits. ''' user = bundle.request.user bundle.data['created_by'] = user bundle = super(ExperimentResource, self).obj_create(bundle, **kwargs) return bundle
class PipelineInstanceResource(ModelResource): data = fields.ForeignKey(SnapshotResource, 'snapshot') exec_data = fields.ForeignKey(SnapshotResource, 'execution_snapshot') template = fields.ForeignKey(PipelineTemplateResource, 'template') pop_keys = [ 'is_deleted', 'edit_time', 'create_time', 'snapshot', 'template', 'is_finished', 'is_started', 'finish_time', 'start_time', 'instance_id', 'execution_snapshot' ] class Meta: queryset = PipelineInstance.objects.filter(is_deleted=False) resource_name = 'instances' excludes = ['is_deleted', 'id'] always_return_data = True detail_uri_name = 'instance_id' list_allowed_method = ['get', 'post'] detail_allowed_methods = ['get', 'patch', 'post', 'delete'] filtering = { 'template': ALL_WITH_RELATIONS, } authorization = Authorization() serializer = PipelineSerializer() def dehydrate_data(self, bundle): return json.dumps(bundle.obj.snapshot.data) def dehydrate_exec_data(self, bundle): return json.dumps(bundle.obj.execution_snapshot.data) def hydrate(self, bundle): for key in self.pop_keys: if key in bundle.data: bundle.data.pop(key) return super(PipelineInstanceResource, self).hydrate(bundle) def alter_list_data_to_serialize(self, request, data): for bundle in data['objects']: bundle.data.pop('data') bundle.data.pop('exec_data') bundle.data.pop('description') bundle.data.pop('template') return data def alter_detail_data_to_serialize(self, request, data): bundle = data bundle.data.pop('template') return data def obj_create(self, bundle, **kwargs): template_id = bundle.data.get('template_id') try: template = PipelineTemplate.objects.get(template_id=template_id) except Exception: raise_validation_error(self, bundle, 'instances', 'template_id', _(u"模板不存在")) exec_data = bundle.data.get('exec_data') try: exec_data = json.loads(exec_data) except Exception: raise_validation_error(self, bundle, 'instances', 'exec_data', _(u"JSON 格式不合法")) # unfold subprocess unfold_subprocess(exec_data) instance_id = node_uniqid() exec_data['id'] = instance_id exec_snapshot, __ = Snapshot.objects.create_or_get_snapshot(exec_data) kwargs['template_id'] = template.id kwargs['instance_id'] = instance_id kwargs['snapshot_id'] = template.snapshot.id kwargs['execution_snapshot_id'] = exec_snapshot.id bundle.data.pop('exec_data') return super(PipelineInstanceResource, self).obj_create(bundle, **kwargs) def obj_update(self, bundle, skip_errors=False, **kwargs): exec_data = bundle.data['exec_data'] try: data = json.loads(exec_data) except Exception: raise_validation_error(self, bundle, 'instances', 'exec_data', _(u"JSON 格式不合法")) bundle.obj.execution_snapshot, __ = Snapshot.objects.create_or_get_snapshot( data) bundle.data.pop('exec_data') bundle.data.pop('data') return super(PipelineInstanceResource, self).obj_update(bundle, skip_errors=skip_errors, **kwargs) def obj_delete(self, bundle, **kwargs): instance_id = kwargs['instance_id'] PipelineInstance.objects.delete_model(instance_id)
class DatasetResource(MyTardisModelResource): experiments = fields.ToManyField(ExperimentResource, 'experiments', related_name='datasets') parameter_sets = fields.ToManyField( 'tardis.tardis_portal.api.DatasetParameterSetResource', 'datasetparameterset_set', related_name='dataset', full=True, null=True) instrument = fields.ForeignKey(InstrumentResource, 'instrument', null=True, full=True) class Meta(MyTardisModelResource.Meta): queryset = Dataset.objects.all() filtering = { 'id': ('exact', ), 'experiments': ALL_WITH_RELATIONS, 'description': ('exact', ), 'directory': ('exact', ), 'instrument': ALL_WITH_RELATIONS, } ordering = ['id', 'description'] always_return_data = True def prepend_urls(self): return [ url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/files/' r'(?:(?P<file_path>.+))?$' % self._meta.resource_name, self.wrap_view('get_datafiles'), name='api_get_datafiles_for_dataset'), ] def get_datafiles(self, request, **kwargs): file_path = kwargs.get('file_path', None) dataset_id = kwargs['pk'] datafiles = DataFile.objects.filter(dataset__id=dataset_id) auth_bundle = self.build_bundle(request=request) auth_bundle.obj = DataFile() self.authorized_read_list(datafiles, auth_bundle) del kwargs['pk'] del kwargs['file_path'] kwargs['dataset__id'] = dataset_id if file_path is not None: kwargs['directory__startswith'] = file_path df_res = DataFileResource() return df_res.dispatch('list', request, **kwargs) def hydrate_m2m(self, bundle): ''' Create experiment-dataset associations first, because they affect authorization for adding other related resources, e.g. metadata ''' if getattr(bundle.obj, 'id', False): for exp_uri in bundle.data.get('experiments', []): try: exp = ExperimentResource.get_via_uri( ExperimentResource(), exp_uri, bundle.request) bundle.obj.experiments.add(exp) except NotFound: pass return super(DatasetResource, self).hydrate_m2m(bundle)
class JournalResource(ModelResource): missions = fields.CharField(readonly=True) other_titles = fields.CharField(readonly=True) creator = fields.ForeignKey(UserResource, 'creator') abstract_keyword_languages = fields.CharField(readonly=True) languages = fields.CharField(readonly=True) use_license = fields.ForeignKey(UseLicenseResource, 'use_license', full=True) sponsors = fields.ManyToManyField(SponsorResource, 'sponsor') collections = fields.ManyToManyField(CollectionResource, 'collections') issues = fields.OneToManyField(IssueResource, 'issue_set') sections = fields.OneToManyField(SectionResource, 'section_set') pub_status_history = fields.ListField(readonly=True) contact = fields.DictField(readonly=True) study_areas = fields.ListField(readonly=True) pub_status = fields.CharField(readonly=True) pub_status_reason = fields.CharField(readonly=True) #recursive field previous_title = fields.ForeignKey('self', 'previous_title', null=True) class Meta(ApiKeyAuthMeta): queryset = Journal.objects.all().filter() resource_name = 'journals' allowed_methods = [ 'get', ] filtering = { 'is_trashed': ('exact', ), 'eletronic_issn': ('exact', ), 'print_issn': ('exact', ), } def build_filters(self, filters=None): """ Custom filter that retrieves data by the collection's name_slug. """ if filters is None: filters = {} orm_filters = super(JournalResource, self).build_filters(filters) if 'collection' in filters: journals = Journal.objects.filter( collections__name_slug=filters['collection']) orm_filters['pk__in'] = journals if 'pubstatus' in filters: # keep the previous filtering try: j = orm_filters['pk__in'] except KeyError: j = Journal.objects statuses = filters.getlist('pubstatus') journals = j.filter(membership__status__in=statuses) orm_filters['pk__in'] = journals return orm_filters def dehydrate_missions(self, bundle): return [(mission.language.iso_code, mission.description) for mission in bundle.obj.missions.all()] def dehydrate_other_titles(self, bundle): return [(title.category, title.title) for title in bundle.obj.other_titles.all()] def dehydrate_languages(self, bundle): return [language.iso_code for language in bundle.obj.languages.all()] def dehydrate_pub_status_history(self, bundle): return [{ 'date': event.since, 'status': event.status } for event in bundle.obj.statuses.order_by('-since').all()] def dehydrate_study_areas(self, bundle): return [area.study_area for area in bundle.obj.study_areas.all()] def dehydrate_collections(self, bundle): """Only works com v1, without multiple collections per journal. """ try: return bundle.data['collections'][0] except IndexError: return '' def dehydrate_pub_status(self, bundle): col = bundle.obj.collections.get() return bundle.obj.membership_info(col, 'status') def dehydrate_pub_status_reason(self, bundle): col = bundle.obj.collections.get() return bundle.obj.membership_info(col, 'reason')
class DataFileResource(MyTardisModelResource): dataset = fields.ForeignKey(DatasetResource, 'dataset') parameter_sets = fields.ToManyField( 'tardis.tardis_portal.api.DatafileParameterSetResource', 'datafileparameterset_set', related_name='datafile', full=True, null=True) datafile = fields.FileField() replicas = fields.ToManyField('tardis.tardis_portal.api.ReplicaResource', 'file_objects', related_name='datafile', full=True, null=True) temp_url = None class Meta(MyTardisModelResource.Meta): queryset = DataFile.objects.all() filtering = { 'directory': ('exact', 'startswith'), 'dataset': ALL_WITH_RELATIONS, 'filename': ('exact', ), } ordering = ['id', 'filename', 'modification_time'] resource_name = 'dataset_file' def download_file(self, request, **kwargs): ''' curl needs the -J switch to get the filename right auth needs to be added manually here ''' self.method_check(request, allowed=['get']) self.is_authenticated(request) self.throttle_check(request) if not has_datafile_download_access(request=request, datafile_id=kwargs['pk']): return HttpResponseForbidden() file_record = self._meta.queryset.get(pk=kwargs['pk']) self.authorized_read_detail([file_record], self.build_bundle(obj=file_record, request=request)) preferred_dfo = file_record.get_preferred_dfo() if not preferred_dfo: # No verified DataFileObject exists for this DataFile return HttpResponseNotFound() storage_class_name = preferred_dfo.storage_box.django_storage_class download_uri_templates = getattr(settings, 'DOWNLOAD_URI_TEMPLATES', {}) if storage_class_name in download_uri_templates: template = URITemplate(download_uri_templates[storage_class_name]) return redirect(template.expand(dfo_id=preferred_dfo.id)) file_object = file_record.get_file() wrapper = FileWrapper(file_object) tracker_data = dict(label='file', session_id=request.COOKIES.get('_ga'), ip=request.META.get('REMOTE_ADDR', ''), user=request.user, total_size=file_record.size, num_files=1, ua=request.META.get('HTTP_USER_AGENT', None)) response = StreamingHttpResponse(IteratorTracker( wrapper, tracker_data), content_type=file_record.mimetype) response['Content-Length'] = file_record.size response['Content-Disposition'] = 'attachment; filename="%s"' % \ file_record.filename self.log_throttled_access(request) return response def verify_file(self, request, **kwargs): '''triggers verification of file, e.g. after non-POST upload complete ''' self.method_check(request, allowed=['get']) self.is_authenticated(request) self.throttle_check(request) if not has_datafile_download_access(request=request, datafile_id=kwargs['pk']): return HttpResponseForbidden() file_record = self._meta.queryset.get(pk=kwargs['pk']) self.authorized_read_detail([file_record], self.build_bundle(obj=file_record, request=request)) for dfo in file_record.file_objects.all(): shadow = 'dfo_verify location:%s' % dfo.storage_box.name tasks.dfo_verify.apply_async(args=[dfo.id], priority=dfo.priority, shadow=shadow) return HttpResponse() def hydrate(self, bundle): if 'attached_file' in bundle.data: # have POSTed file newfile = bundle.data['attached_file'][0] compute_md5 = getattr(settings, 'COMPUTE_MD5', True) compute_sha512 = getattr(settings, 'COMPUTE_SHA512', False) if (compute_md5 and 'md5sum' not in bundle.data) or \ (compute_sha512 and 'sha512sum' not in bundle.data): checksums = compute_checksums(newfile, compute_md5=compute_md5, compute_sha512=compute_sha512, close_file=False) if compute_md5: bundle.data['md5sum'] = checksums['md5sum'] if compute_sha512: bundle.data['sha512sum'] = checksums['sha512sum'] if 'replicas' in bundle.data: for replica in bundle.data['replicas']: replica.update({'file_object': newfile}) else: bundle.data['replicas'] = [{'file_object': newfile}] del (bundle.data['attached_file']) return bundle def obj_create(self, bundle, **kwargs): ''' Creates a new DataFile object from the provided bundle.data dict. If a duplicate key error occurs, responds with HTTP Error 409: CONFLICT ''' try: retval = super(DataFileResource, self).obj_create(bundle, **kwargs) except IntegrityError as err: if "duplicate key" in str(err): raise ImmediateHttpResponse(HttpResponse(status=409)) raise if 'replicas' not in bundle.data or not bundle.data['replicas']: # no replica specified: return upload path and create dfo for # new path sbox = bundle.obj.get_receiving_storage_box() if sbox is None: raise NotImplementedError dfo = DataFileObject(datafile=bundle.obj, storage_box=sbox) dfo.create_set_uri() dfo.save() self.temp_url = dfo.get_full_path() return retval def post_list(self, request, **kwargs): response = super(DataFileResource, self).post_list(request, **kwargs) if self.temp_url is not None: response.content = self.temp_url self.temp_url = None return response def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/download%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('download_file'), name="api_download_file"), url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/verify%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('verify_file'), name="api_verify_file"), ] def deserialize(self, request, data, format=None): ''' from https://github.com/toastdriven/django-tastypie/issues/42 modified to deserialize json sent via POST. Would fail if data is sent in a different format. uses a hack to get back pure json from request.POST ''' if not format: format = request.META.get('CONTENT_TYPE', 'application/json') if format == 'application/x-www-form-urlencoded': return request.POST if format.startswith('multipart'): jsondata = request.POST['json_data'] data = json.loads(jsondata) data.update(request.FILES) return data return super(DataFileResource, self).deserialize(request, data, format) def put_detail(self, request, **kwargs): ''' from https://github.com/toastdriven/django-tastypie/issues/42 ''' if request.META.get('CONTENT_TYPE').startswith('multipart') and \ not hasattr(request, '_body'): request._body = '' return super(DataFileResource, self).put_detail(request, **kwargs)
class IssueResource(ModelResource): journal = fields.ForeignKey('api.resources.JournalResource', 'journal') sections = fields.ManyToManyField(SectionResource, 'section') thematic_titles = fields.CharField(readonly=True) is_press_release = fields.BooleanField(readonly=True) suppl_volume = fields.CharField(readonly=True) suppl_number = fields.CharField(readonly=True) class Meta(ApiKeyAuthMeta): queryset = Issue.objects.all() resource_name = 'issues' allowed_methods = [ 'get', ] filtering = { "journal": ('exact'), "is_marked_up": ('exact'), "volume": ('exact'), "number": ('exact'), "publication_year": ('exact'), "suppl_number": ('exact'), "suppl_volume": ('exact') } def build_filters(self, filters=None): """ Custom filter that retrieves data by the collection's name_slug. """ if filters is None: filters = {} orm_filters = super(IssueResource, self).build_filters(filters) if 'collection' in filters: issues = Issue.objects.filter( journal__collection__name_slug=filters['collection']) orm_filters['pk__in'] = issues if 'eletronic_issn' in filters: issues = Issue.objects.filter( journal__eletronic_issn=filters['eletronic_issn']) orm_filters['pk__in'] = issues if 'print_issn' in filters: issues = Issue.objects.filter( journal__print_issn=filters['print_issn']) orm_filters['pk__in'] = issues return orm_filters def dehydrate_thematic_titles(self, bundle): return dict([title.language.iso_code, title.title] for title in bundle.obj.issuetitle_set.all()) def dehydrate_is_press_release(self, bundle): return False def dehydrate_suppl_volume(self, bundle): if bundle.obj.type == 'supplement': return bundle.obj.suppl_text if bundle.obj.volume else '' else: return '' def dehydrate_suppl_number(self, bundle): if bundle.obj.type == 'supplement': return bundle.obj.suppl_text if bundle.obj.number else '' else: return ''
class DatafileParameterResource(ParameterResource): parameterset = fields.ForeignKey(DatafileParameterSetResource, 'parameterset') class Meta(ParameterResource.Meta): queryset = DatafileParameter.objects.all()
class UserAbuseResource(BaseAbuseResource): user = fields.ForeignKey(AccountResource, attribute='user', full=True) class Meta(BaseAbuseResource.Meta): resource_name = 'user' validation = RequestFormValidation(form_class=UserAbuseForm)
class OMSInstanceResource(ModelResource): host = fields.ForeignKey(OMSHostResource, 'host') class Meta: queryset = OMSInstance.objects.all() resource_name = 'instance'