def get(self, request, *args, **kwargs): self.show_recent = kwargs.pop('show_recent', False) content = kwargs.pop('content', None) if not content: return HttpResponseBadRequest('No content type supplied') self.model = SEARCH_MODEL_NAMES_REVERSE.get(content, None) if not self.model: return HttpResponseBadRequest( 'Unknown content type supplied: "%s"' % content) self.page_size = int( request.GET.get('page_size', self.default_page_size)) if not is_number(self.page_size): return HttpResponseBadRequest( 'Malformed parameter: "page_size": %s' % self.page_size) self.page_size = max(self.min_page_size, min(self.max_page_size, self.page_size)) self.offset_timestamp = request.GET.get('offset_timestamp', self.default_offset_timestamp) if self.offset_timestamp is not None and not is_number( self.offset_timestamp): return HttpResponseBadRequest( 'Malformed parameter: "offset_timestamp"') if self.offset_timestamp is not None and isinstance( self.offset_timestamp, six.string_types): self.offset_timestamp = float(self.offset_timestamp) return super(TypedContentWidgetView, self).get(request, *args, **kwargs)
def get(self, request, *args, **kwargs): """ Accepted GET-params: `page_size` int (optional): Number of items to be returned. If a value larger than `self.max_page_size` is supplied, `self.max_page_size`is used instead. Default: `self.default_page_size` `offset_timestamp` float (optional): If supplied, only items older than the given timestamp are returned. Items with the exact timestamp are excluded. Use this parameter in conjunction with the return value `last_timestamp` for pagination. `only_mine` bool (optional): if True, will only show objects that belong to groups or projects the `user` is a member of. If False, will include all visible items in this portal for the user. """ # require authenticated user self.user = request.user if not request.user.is_authenticated: return HttpResponseForbidden('Not authenticated.') content = kwargs.pop('content', None) if content: self.filter_model = SEARCH_MODEL_NAMES_REVERSE.get(content, None) if not self.filter_model: return HttpResponseBadRequest( 'Unknown content type supplied: "%s"' % content) self.page_size = int( request.GET.get('page_size', self.default_page_size)) if not is_number(self.page_size): return HttpResponseBadRequest( 'Malformed parameter: "page_size": %s' % self.page_size) self.page_size = max(self.min_page_size, min(self.max_page_size, self.page_size)) self.offset_timestamp = request.GET.get('offset_timestamp', self.default_offset_timestamp) if self.offset_timestamp is not None and not is_number( self.offset_timestamp): return HttpResponseBadRequest( 'Malformed parameter: "offset_timestamp"') if self.offset_timestamp is not None and isinstance( self.offset_timestamp, six.string_types): self.offset_timestamp = float(self.offset_timestamp) self.only_mine = request.GET.get('only_mine', self.only_mine_default) if isinstance(self.only_mine, six.string_types): self.only_mine = bool(json.loads(self.only_mine)) items = self.get_items() response = self.render_to_response(items) return response
def get(self, request, *args, **kwargs): self.show_recent = kwargs.pop('show_recent', False) if self.show_recent: self.offset_model_field = 'visited' else: self.offset_model_field = 'created' content = kwargs.pop('content', None) if not content: return HttpResponseBadRequest('No content type supplied') self.model = SEARCH_MODEL_NAMES_REVERSE.get(content, None) if not self.model: return HttpResponseBadRequest( 'Unknown content type supplied: "%s"' % content) return super(TypedContentWidgetView, self).get(request, *args, **kwargs)
def get_items(self): """ Returns a paginated list of items as mixture of different models, in sorted order """ single_querysets = [] for content_type in self.content_types: content_model = SEARCH_MODEL_NAMES_REVERSE.get(content_type, None) if content_model is None: if settings.DEBUG: raise ImproperlyConfigured( 'Could not find content model for timeline content type "%s"' % content_type) continue single_querysets.append( self._get_queryset_for_model( content_model, self.content_type_filter_fields[content_type])) items = self._mix_items_from_querysets(*single_querysets) return items
def get_searchresult_by_args(portal, model_type, slug, user=None): """ Retrieves a HaystackMapResult just as the API would, for a given shortid in the form of `<classid>.<instanceid>` (see `itemid_from_searchresult()`). """ # monkey-hack: if the portal id is 0, we have an external item, so look up the external models if settings.COSINNUS_EXTERNAL_CONTENT_ENABLED and portal == EXTERNAL_CONTENT_PORTAL_ID: from cosinnus.models.map import EXTERNAL_SEARCH_MODEL_NAMES_REVERSE model = EXTERNAL_SEARCH_MODEL_NAMES_REVERSE.get(model_type, None) else: model = SEARCH_MODEL_NAMES_REVERSE.get(model_type, None) if model_type == 'people': sqs = SearchQuerySet().models(model).filter_and(slug=slug) elif model_type == 'events': group_slug, slug = slug.split('*', 1) sqs = SearchQuerySet().models(model).filter_and(portal=portal, group_slug=group_slug, slug=slug) else: sqs = SearchQuerySet().models(model).filter_and(portal=portal, slug=slug) if user: # filter for read access by this user sqs = filter_searchqueryset_for_read_access(sqs, user) # hack: haystack seems to be unable to filter *exact* on `slug` (even when using __exact). # this affects slugs like `my-slug` vs `my-slug-2`. # so we manually post-filter on slug to get an exact match if len(sqs) > 1: sqs = [result for result in sqs if result.slug == slug] if len(sqs) != 1: logger.warn( 'Got a DetailMap request where %d indexed results were found!' % len(sqs), extra={ 'portal': portal, 'model': model, 'slug': slug, }) return None return sqs[0]
def get_items(self): """ Returns a paginated list of items as mixture of different models, in sorted order """ if self.filter_model: single_querysets = [ self._get_queryset_for_model(self.filter_model) ] else: single_querysets = [] for content_type in self.content_types: content_model = SEARCH_MODEL_NAMES_REVERSE.get( content_type, None) if content_model is None: if settings.DEBUG: logger.warn( 'Could not find content model for timeline content type "%s"' % content_type) continue single_querysets.append( self._get_queryset_for_model(content_model)) items = self._mix_items_from_querysets(*single_querysets) return items
def map_detail_endpoint(request): """ Maps API object detail endpoint using pSQL results. For parameters see ``MAP_DETAIL_PARAMETERS`` returns JSON with the contents of type ``DetailedMapResult`` """ params = _collect_parameters(request.GET, MAP_DETAIL_PARAMETERS) portal = params['portal'] slug = params['slug'] model_type = params['type'] if not is_number(portal) or portal < 0: return HttpResponseBadRequest( '``portal`` param must be a positive number!') if not slug: return HttpResponseBadRequest('``slug`` param must be supplied!') slug = force_text(slug) # stringify is necessary for number-only slugs if not model_type or not isinstance(model_type, six.string_types): return HttpResponseBadRequest( '``type`` param must be supplied and be a string!') if portal == 0: portal = CosinnusPortal.get_current().id # try to retrieve the requested object model = SEARCH_MODEL_NAMES_REVERSE.get(model_type, None) if model is None: return HttpResponseBadRequest( '``type`` param indicated an invalid data model type!') # TODO: for groups/projects we should really use the cache here. if model_type == 'people': # UserProfiles are retrieved independent of the portal obj = get_object_or_None(get_user_profile_model(), user__username=slug) elif model_type == 'events': group_slug, event_slug = slug.split('*', 1) obj = get_object_or_None(model, group__portal__id=portal, group__slug=group_slug, slug=event_slug) else: obj = get_object_or_None(model, portal__id=portal, slug=slug) if obj is None: return HttpResponseNotFound( 'No item found that matches the requested type and slug (obj: %s, %s, %s).' % (escape(force_text(model)), portal, slug)) # check read permission if not model_type in SEARCH_MODEL_TYPES_ALWAYS_READ_PERMISSIONS and not check_object_read_access( obj, request.user): return HttpResponseForbidden( 'You do not have permission to access this item.') # get the basic result data from the search index (as it is already prepared and faster to access there) haystack_result = get_searchresult_by_args(portal, model_type, slug) if not haystack_result: return HttpResponseNotFound( 'No item found that matches the requested type and slug (index: %s, %s, %s).' % (portal, model_type, slug)) # format data result_model = SEARCH_RESULT_DETAIL_TYPE_MAP[model_type] result = result_model(haystack_result, obj, request.user) data = { 'result': result, } return JsonResponse(data)