def user_category_filter(queryset, user): """ Returns Queryset containing only user's prefered content (filtering based on categories). If queryset.model has no relation to ella.core.models.Category, original queryset is returned. """ from ella.newman.permission import model_category_fk, is_category_model qs = queryset category_fk = model_category_fk(qs.model) if not category_fk: return qs root_category_ids = get_user_config(user, CATEGORY_FILTER) if not root_category_ids: # user has no custom category filter set or his filter set is empty. return qs if not user.is_superuser: helper = models.DenormalizedCategoryUserRole.objects.filter( user_id=user.pk, root_category_id__in=root_category_ids ).values('category_id') user_categories = [c['category_id'] for c in helper] if is_category_model(qs.model): lookup = 'id__in' else: lookup = '%s__in' % category_fk.name out = qs.filter(**{lookup: user_categories}) else: cats = Category.objects.filter(pk__in=root_category_ids).values('site__pk') user_sites = [c['site__pk'] for c in cats] if is_category_model(qs.model): lookup = 'site__id__in' else: lookup = '%s__site__id__in' % category_fk.name out = qs.filter(**{lookup: user_sites}) flag_queryset(out, 'user_category_filtered', True) return out
def user_category_filter(queryset, user): """ Returns Queryset containing only user's prefered content (filtering based on categories). If queryset.model has no relation to ella.core.models.Category, original queryset is returned. """ from ella.newman.permission import model_category_fk, is_category_model qs = queryset category_fk = model_category_fk(qs.model) if not category_fk: return qs root_category_ids = get_user_config(user, newman_settings.CATEGORY_FILTER) if not root_category_ids: # user has no custom category filter set or his filter set is empty. return qs if not user.is_superuser: helper = models.DenormalizedCategoryUserRole.objects.filter( user_id=user.pk, root_category_id__in=root_category_ids).values('category_id') user_categories = [c['category_id'] for c in helper] if is_category_model(qs.model): lookup = 'id__in' else: lookup = '%s__in' % category_fk.name out = qs.filter(**{lookup: user_categories}) else: cats = Category.objects.filter( pk__in=root_category_ids).values('site__pk') user_sites = [c['site__pk'] for c in cats] if is_category_model(qs.model): lookup = 'site__id__in' else: lookup = '%s__site__id__in' % category_fk.name out = qs.filter(**{lookup: user_sites}) flag_queryset(out, 'user_category_filtered', True) return out
def suggest_view(self, request, extra_context=None): self.register_newman_variables(request) SUGGEST_VIEW_LIMIT = getattr(settings, 'SUGGEST_VIEW_LIMIT', 20) SUGGEST_VIEW_MIN_LENGTH = getattr(settings, 'SUGGEST_VIEW_MIN_LENGTH', 2) if not ('f' in request.GET.keys() and 'q' in request.GET.keys()): raise AttributeError, 'Invalid query attributes. Example: ".../?f=field_a&f=field_b&q=search_term&o=offset"' elif len(request.GET.get('q')) < SUGGEST_VIEW_MIN_LENGTH: return HttpResponse( '', mimetype='text/plain;charset=utf-8' ) offset = 0 if 'o' in request.GET.keys() and request.GET.get('o'): offset = int(request.GET.get('o')) limit = offset + SUGGEST_VIEW_LIMIT model_fields = [mf.name for mf in self.model._meta.fields] lookup_fields = [] lookup_value = request.GET.get('q') lookup = None has_non_lookup_attr = False all_fields = [u'id'] + request.GET.getlist('f') for lf in all_fields: if lf in model_fields or lf.split('__')[0] in model_fields: lookup_fields.append(lf) elif hasattr(self.model, lf): has_non_lookup_attr = True else: raise AttributeError, 'Model "%s" has not field "%s". Possible fields are "%s".' \ % (self.model._meta.object_name, lf, ', '.join(model_fields)) for f in lookup_fields: lookup_key = str('%s__icontains' % f) if not lookup: lookup = models.Q(**{lookup_key: lookup_value}) else: lookup = lookup | models.Q(**{lookup_key: lookup_value}) # user role based category filtering if not is_category_model(self.model): category_field = model_category_fk(self.model) if category_field and request.user: applicable = applicable_categories(request.user) args_lookup = { '%s__in' % category_field.name: applicable} lookup = lookup & models.Q(**args_lookup) else: applicable = applicable_categories(request.user) lookup = lookup & models.Q(pk__in=applicable) # user category filter qs = utils.user_category_filter(self.model.objects.filter(lookup), request.user) if not has_non_lookup_attr: data = qs.values(*lookup_fields) else: data = qs.only(*lookup_fields) def construct_row(inst, fields): row = {} for f in fields: attr = getattr(inst, f) if callable(attr): row[f] = attr() else: row[f] = attr row[f] = truncatewords(striptags(unicode(row[f])), 5) return row if has_non_lookup_attr: outdata = [] for i in data: outdata.append(construct_row(i, all_fields)) data = outdata # sort the suggested items so that those starting with the sought term come first def compare(a,b): def _cmp(a,b,sought): a_starts = unicode(a).lower().startswith(sought) b_starts = unicode(b).lower().startswith(sought) # if exactly one of (a,b) starts with sought, the one starting with it comes first if a_starts ^ b_starts: if a_starts: return -1 if b_starts: return +1 # else compare lexicographically return cmp(a,b) return _cmp(a,b,unicode(lookup_value).lower()) cnt = len(data) data = list(data) if offset >= len(data): return HttpResponse('SPECIAL: OFFSET OUT OF RANGE', mimetype='text/plain') data.sort(cmp=compare, key=lambda x: x[lookup_fields[1]]) data = data[offset:limit] ft = [] ft.append('{cnt:%d}' % cnt) for item in data: ft.append( "%s".encode('utf-8') % '|'.join("%s" % item[f] for f in all_fields) ) return HttpResponse( '\n'.join(ft), mimetype='text/plain;charset=utf-8' )
def suggest_view(self, request, extra_context=None): self.register_newman_variables(request) if not ('f' in request.GET.keys() and 'q' in request.GET.keys()): raise AttributeError, 'Invalid query attributes. Example: ".../?f=field_a&f=field_b&q=search_term&o=offset"' elif len(request.GET.get( 'q')) < newman_settings.SUGGEST_VIEW_MIN_LENGTH: return HttpResponse('', mimetype='text/plain;charset=utf-8') offset = 0 if 'o' in request.GET.keys() and request.GET.get('o'): offset = int(request.GET.get('o')) limit = offset + newman_settings.SUGGEST_VIEW_LIMIT model_fields = [mf.name for mf in self.model._meta.fields] lookup_fields = [] lookup_value = request.GET.get('q') lookup = None has_non_lookup_attr = False all_fields = [u'id'] + request.GET.getlist('f') for lf in all_fields: if lf in model_fields or lf.split('__')[0] in model_fields: lookup_fields.append(lf) elif hasattr(self.model, lf): has_non_lookup_attr = True else: raise AttributeError, 'Model "%s" has not field "%s". Possible fields are "%s".' \ % (self.model._meta.object_name, lf, ', '.join(model_fields)) for f in lookup_fields: lookup_key = str('%s__icontains' % f) if not lookup: lookup = models.Q(**{lookup_key: lookup_value}) else: lookup = lookup | models.Q(**{lookup_key: lookup_value}) # user role based category filtering if not is_category_model(self.model): category_field = model_category_fk(self.model) if category_field and request.user: applicable = applicable_categories(request.user) args_lookup = {'%s__in' % category_field.name: applicable} lookup = lookup & models.Q(**args_lookup) else: applicable = applicable_categories(request.user) lookup = lookup & models.Q(pk__in=applicable) # user category filter qs = utils.user_category_filter(self.model.objects.filter(lookup), request.user) if not has_non_lookup_attr: data = qs.values(*lookup_fields) else: data = qs.only(*lookup_fields) def construct_row(inst, fields): row = {} for f in fields: attr = getattr(inst, f) if callable(attr): row[f] = attr() else: row[f] = attr row[f] = truncatewords(striptags(unicode(row[f])), 5) return row if has_non_lookup_attr: outdata = [] for i in data: outdata.append(construct_row(i, all_fields)) data = outdata # sort the suggested items so that those starting with the sought term come first def compare(a, b): def _cmp(a, b, sought): a_starts = unicode(a).lower().startswith(sought) b_starts = unicode(b).lower().startswith(sought) # if exactly one of (a,b) starts with sought, the one starting with it comes first if a_starts ^ b_starts: if a_starts: return -1 if b_starts: return +1 # else compare lexicographically return cmp(a, b) return _cmp(a, b, unicode(lookup_value).lower()) cnt = len(data) data = list(data) if offset >= len(data): return HttpResponse('SPECIAL: OFFSET OUT OF RANGE', mimetype='text/plain') data.sort(cmp=compare, key=lambda x: x[lookup_fields[1]]) data = data[offset:limit] ft = [] ft.append('{cnt:%d}' % cnt) for item in data: ft.append("%s".encode('utf-8') % '|'.join("%s" % item[f] for f in all_fields)) return HttpResponse('\n'.join(ft), mimetype='text/plain;charset=utf-8')