def test_sorting_mixed(self): translation.activate('de') q = TranslatedModel.objects.all() expected = [1, 4, 3] eq_(ids(order_by_translation(q, 'name')), expected) eq_(ids(order_by_translation(q, '-name')), list(reversed(expected)))
def test_sorting_en(self): q = TranslatedModel.objects.all() expected = [4, 1, 3] assert ids(order_by_translation(q, 'name')) == expected assert ids(order_by_translation(q, '-name')) == (list(reversed(expected)))
def test_sorting_en(self): q = TranslatedModel.objects.all() expected = [4, 1, 3] assert ids(order_by_translation(q, 'name')) == expected assert ids(order_by_translation(q, '-name')) == ( list(reversed(expected)))
def test_sorting_mixed(self): translation.activate('de') q = TranslatedModel.objects.all() expected = [1, 4, 3] eq_(ids(order_by_translation(q, 'name')), expected) eq_(ids(order_by_translation(q, '-name')), list(reversed(expected)))
def test_sorting_by_field(self): field = TranslatedModel._meta.get_field('default_locale') fallback = classmethod(lambda cls: field) with patch.object(TranslatedModel, 'get_fallback', fallback, create=True): translation.activate('de') qs = TranslatedModel.objects.all() expected = [3, 1, 4] assert ids(order_by_translation(qs, 'name')) == expected assert ids(order_by_translation(qs, '-name')) == (list(reversed(expected)))
def test_sorting_by_field(self): field = TranslatedModel._meta.get_field('default_locale') TranslatedModel.get_fallback = classmethod(lambda cls: field) translation.activate('de') q = TranslatedModel.objects.all() expected = [3, 1, 4] eq_(ids(order_by_translation(q, 'name')), expected) eq_(ids(order_by_translation(q, '-name')), list(reversed(expected))) del TranslatedModel.get_fallback
def test_sorting_by_field(self): field = TranslatedModel._meta.get_field('default_locale') fallback = classmethod(lambda cls: field) with patch.object(TranslatedModel, 'get_fallback', fallback, create=True): translation.activate('de') qs = TranslatedModel.objects.all() expected = [3, 1, 4] assert ids(order_by_translation(qs, 'name')) == expected assert ids(order_by_translation(qs, '-name')) == ( list(reversed(expected)))
def test_sorting_by_field_with_related_model(self): # This time we sort a "regular" queryset through a relation that # contains a translated field. container = ContainsManyToManyToTranslatedModel.objects.create() to_one = ContainsTranslatedThrough.objects.create( container=container, target=TranslatedModel.objects.get(pk=1)) to_three = ContainsTranslatedThrough.objects.create( container=container, target=TranslatedModel.objects.get(pk=3)) to_four = ContainsTranslatedThrough.objects.create( container=container, target=TranslatedModel.objects.get(pk=4)) # We also add another TranslatedModel object that doesn't have a # translation in 'en-US' or 'de'. translation.activate('fr') five = TranslatedModel.objects.create(default_locale='fr', name='a français') to_five = ContainsTranslatedThrough.objects.create(container=container, target=five) def get_queryset(): # FIXME: We force a join with TranslatedModel, because otherwise # order_by_translation isn't smart enough to do it itself. return ContainsTranslatedThrough.objects.filter( target__name_id__gt=0) # First, no fallback. The "five" instance is absent, because there is # no translation matching 'de' or settings.LANGUAGE_CODE (en-US). translation.activate('de') qs = get_queryset() expected = [to_one.pk, to_four.pk, to_three.pk] assert ids(order_by_translation(qs, 'name', TranslatedModel)) == expected assert ids(order_by_translation(qs, '-name', TranslatedModel)) == (list( reversed(expected))) # Second, with fallback. This changes what translations are available, # causing "to_five" to be found, and "to_three" to be higher, because # we pick up its translation matching their default_locale. field = TranslatedModel._meta.get_field('default_locale') fallback = classmethod(lambda cls: field) with patch.object(TranslatedModel, 'get_fallback', fallback, create=True): qs = get_queryset() expected = [to_five.pk, to_three.pk, to_one.pk, to_four.pk] assert ids(order_by_translation(qs, 'name', TranslatedModel)) == expected assert ids(order_by_translation(qs, '-name', TranslatedModel)) == (list( reversed(expected)))
def test_sorting_by_field(self): field = TranslatedModel._meta.get_field('default_locale') TranslatedModel.get_fallback = classmethod(lambda cls: field) translation.activate('de') q = TranslatedModel.objects.all() expected = [3, 1, 4] eq_(ids(order_by_translation(q, 'name')), expected) eq_(ids(order_by_translation(q, '-name')), list(reversed(expected))) del TranslatedModel.get_fallback
def personas_listing(request, category_slug=None): # Common pieces used by browse and search. TYPE = amo.ADDON_PERSONA q = Category.objects.filter(type=TYPE) categories = order_by_translation(q, 'name') frozen = list(FrozenAddon.objects.values_list('addon', flat=True)) base = Addon.objects.public().filter(type=TYPE).exclude(id__in=frozen) cat = None if category_slug is not None: try: cat = Category.objects.filter(slug=category_slug, type=TYPE)[0] except IndexError: # Maybe it's a Complete Theme? try: cat = Category.objects.filter(slug=category_slug, type=amo.ADDON_THEME)[0] except IndexError: raise Http404 else: # Hey, it was a Complete Theme. url = reverse('browse.themes', args=[cat.slug]) if 'sort' in request.GET: url = amo.utils.urlparams(url, sort=request.GET['sort']) return redirect(url, permanent=not settings.DEBUG) base = base.filter(categories__id=cat.id) filter_ = PersonasFilter(request, base, key='sort', default='up-and-coming') return categories, filter_, base, cat
def my_addons(self, n=8, with_unlisted=False): """Returns n addons""" addons = self.addons if with_unlisted: addons = self.addons.model.with_unlisted.filter(authors=self) qs = order_by_translation(addons, 'name') return qs[:n]
def themes(request, user, category=None): cats = Category.objects.filter(type=amo.ADDON_PERSONA) ctx = { 'profile': user, 'categories': order_by_translation(cats, 'name'), 'search_cat': 'themes' } if user.is_artist: base = user.addons.reviewed().filter( type=amo.ADDON_PERSONA, addonuser__user=user, addonuser__listed=True) if category: qs = cats.filter(slug=category) ctx['category'] = cat = get_list_or_404(qs)[0] base = base.filter(categories__id=cat.id) else: base = Addon.objects.none() filter_ = PersonasFilter(request, base, key='sort', default='popular') addons = amo.utils.paginate(request, filter_.qs, 30, count=base.count()) ctx.update({ 'addons': addons, 'filter': filter_, 'sorting': filter_.field, 'sort_opts': filter_.opts }) return render(request, 'browse/personas/grid.html', ctx)
def my_addons(self, n=8, with_unlisted=False): """Returns n addons""" addons = self.addons if with_unlisted: addons = self.addons.model.with_unlisted.filter(authors=self) qs = order_by_translation(addons, 'name') return qs[:n]
def personas_listing(request, category_slug=None): # Common pieces used by browse and search. TYPE = amo.ADDON_PERSONA q = Category.objects.filter(type=TYPE) categories = order_by_translation(q, 'name') frozen = list(FrozenAddon.objects.values_list('addon', flat=True)) base = Addon.objects.public().filter(type=TYPE).exclude(id__in=frozen) cat = None if category_slug is not None: try: cat = Category.objects.filter(slug=category_slug, type=TYPE)[0] except IndexError: # Maybe it's a Complete Theme? try: cat = Category.objects.filter(slug=category_slug, type=amo.ADDON_THEME)[0] except IndexError: raise Http404 else: # Hey, it was a Complete Theme. url = reverse('browse.themes', args=[cat.slug]) if 'sort' in request.GET: url = amo.utils.urlparams(url, sort=request.GET['sort']) return redirect(url, permanent=not settings.DEBUG) base = base.filter(categories__id=cat.id) filter_ = PersonasFilter(request, base, key='sort', default='up-and-coming') return categories, filter_, base, cat
def search_tools(request, category=None): """View the search tools page.""" APP, TYPE = request.APP, amo.ADDON_SEARCH qs = Category.objects.filter(application=APP.id, type=TYPE) categories = order_by_translation(qs, 'name') addons, filter = addon_listing(request, [TYPE], SearchToolsFilter, 'popular') if category: category = get_object_or_404(qs, slug=category) addons = addons.filter(categories__id=category.id) addons = amo.utils.paginate(request, addons) base = (Addon.objects.listed( request.APP, amo.STATUS_PUBLIC).filter(type=amo.ADDON_EXTENSION)) sidebar_ext = SearchExtensionsFilter(request, base, 'sort', 'popular') return render( request, 'browse/search_tools.html', { 'categories': categories, 'category': category, 'addons': addons, 'filter': filter, 'search_extensions_filter': sidebar_ext })
def themes(request, user, category=None): cats = Category.objects.filter(type=amo.ADDON_PERSONA) ctx = { 'profile': user, 'categories': order_by_translation(cats, 'name'), 'search_cat': 'themes' } if user.is_artist: base = user.addons.reviewed().filter(type=amo.ADDON_PERSONA, addonuser__user=user, addonuser__listed=True) if category: qs = cats.filter(slug=category) ctx['category'] = cat = get_list_or_404(qs)[0] base = base.filter(categories__id=cat.id) else: base = Addon.objects.none() filter_ = PersonasFilter(request, base, key='sort', default='popular') addons = amo.utils.paginate(request, filter_.qs, 30, count=base.count()) ctx.update({ 'addons': addons, 'filter': filter_, 'sorting': filter_.field, 'sort_opts': filter_.opts }) return render(request, 'browse/personas/grid.html', ctx)
def sidebar(app): """Populates the sidebar with (categories, types).""" from olympia.addons.models import Category if app is None: return [], [] # We muck with query to make order_by and extra_order_by play nice. q = Category.objects.filter(application=app.id, weight__gte=0, type=amo.ADDON_EXTENSION) categories = order_by_translation(q, 'name') categories.query.extra_order_by.insert(0, 'weight') Type = collections.namedtuple('Type', 'id name url') base = urlresolvers.reverse('home') types = [Type(99, _('Collections'), base + 'collections/')] shown_types = { amo.ADDON_PERSONA: urlresolvers.reverse('browse.personas'), amo.ADDON_DICT: urlresolvers.reverse('browse.language-tools'), amo.ADDON_SEARCH: urlresolvers.reverse('browse.search-tools'), amo.ADDON_THEME: urlresolvers.reverse('browse.themes'), } titles = dict(amo.ADDON_TYPES, **{amo.ADDON_DICT: _('Dictionaries & Language Packs')}) for type_, url in shown_types.items(): if type_ in app.types: types.append(Type(type_, titles[type_], url)) return categories, sorted(types, key=lambda x: x.name)
def sidebar(app): """Populates the sidebar with (categories, types).""" from olympia.addons.models import Category if app is None: return [], [] # We muck with query to make order_by and extra_order_by play nice. q = Category.objects.filter(application=app.id, weight__gte=0, type=amo.ADDON_EXTENSION) categories = order_by_translation(q, 'name') categories.query.extra_order_by.insert(0, 'weight') Type = collections.namedtuple('Type', 'id name url') base = urlresolvers.reverse('home') types = [Type(99, _('Collections'), base + 'collections/')] shown_types = { amo.ADDON_PERSONA: urlresolvers.reverse('browse.personas'), amo.ADDON_DICT: urlresolvers.reverse('browse.language-tools'), amo.ADDON_SEARCH: urlresolvers.reverse('browse.search-tools'), amo.ADDON_THEME: urlresolvers.reverse('browse.themes'), } titles = dict(amo.ADDON_TYPES, **{amo.ADDON_DICT: _('Dictionaries & Language Packs')}) for type_, url in shown_types.items(): if type_ in app.types: types.append(Type(type_, titles[type_], url)) return categories, sorted(types, key=lambda x: x.name)
def test_order_by_translations_query_uses_left_outer_join(self): translation.activate('de') qs = TranslatedModel.objects.all() query = unicode(order_by_translation(qs, 'name').query) # There should be 2 LEFT OUTER JOIN to find translations matching # current language and fallback. joins = re.findall('LEFT OUTER JOIN `translations`', query) assert len(joins) == 2
def test_order_by_translations_query_uses_left_outer_join(self): translation.activate('de') qs = TranslatedModel.objects.all() query = unicode(order_by_translation(qs, 'name').query) # There should be 2 LEFT OUTER JOIN to find translations matching # current language and fallback. joins = re.findall('LEFT OUTER JOIN `translations`', query) assert len(joins) == 2
def ajax_list(request): try: addon_id = int(request.GET['addon_id']) except (KeyError, ValueError): return http.HttpResponseBadRequest() qs = Collection.objects.owned_by(request.user).with_has_addon(addon_id) return render(request, 'bandwagon/ajax_list.html', {'collections': order_by_translation(qs, 'name')})
def ajax_list(request): try: addon_id = int(request.GET['addon_id']) except (KeyError, ValueError): return http.HttpResponseBadRequest() qs = Collection.objects.owned_by(request.user).with_has_addon(addon_id) return render(request, 'bandwagon/ajax_list.html', {'collections': order_by_translation(qs, 'name')})
def filter_queryset(self, request, queryset, view): ordering = self.get_ordering(request, queryset, view) if len(ordering) > 1: # We can't support multiple orderings easily because of # how order_by_translation works. raise serializers.ValidationError( 'You can only specify one "sort" argument. Multiple ' 'orderings are not supported') order_by = ordering[0] if order_by in ('name', '-name'): return order_by_translation(queryset, order_by, Addon) sup = super(TranslationAwareOrderingAliasFilter, self) return sup.filter_queryset(request, queryset, view)
def filter_queryset(self, request, queryset, view): ordering = self.get_ordering(request, queryset, view) if len(ordering) > 1: # We can't support multiple orderings easily because of # how order_by_translation works. raise serializers.ValidationError( 'You can only specify one "sort" argument. Multiple ' 'orderings are not supported') order_by = ordering[0] if order_by in ('name', '-name'): return order_by_translation(queryset, order_by, Addon) sup = super(TranslationAwareOrderingAliasFilter, self) return sup.filter_queryset(request, queryset, view)
def search_tools(request, category=None): """View the search tools page.""" APP, TYPE = request.APP, amo.ADDON_SEARCH qs = Category.objects.filter(application=APP.id, type=TYPE) categories = order_by_translation(qs, 'name') addons, filter = addon_listing(request, [TYPE], SearchToolsFilter, 'popular') if category: category = get_object_or_404(qs, slug=category) addons = addons.filter(categories__id=category.id) addons = amo.utils.paginate(request, addons) base = (Addon.objects.listed(request.APP, amo.STATUS_PUBLIC) .filter(type=amo.ADDON_EXTENSION)) sidebar_ext = SearchExtensionsFilter(request, base, 'sort', 'popular') return render(request, 'browse/search_tools.html', {'categories': categories, 'category': category, 'addons': addons, 'filter': filter, 'search_extensions_filter': sidebar_ext})
def my_addons(self, n=8): """Returns n addons""" qs = order_by_translation(self.addons, 'name') return qs[:n]
def filter_name(self): return order_by_translation(self.base_queryset.all(), 'name')
def filter_name(self): return order_by_translation(self.base_queryset, 'name')
def my_addons(self, n=8): """Returns n addons""" qs = order_by_translation(self.addons, 'name') return qs[:n]