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)))
Example #2
0
    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)))
Example #4
0
    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)))
Example #8
0
    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)))
Example #9
0
    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
Example #10
0
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
Example #11
0
 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]
Example #12
0
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)
Example #13
0
 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]
Example #14
0
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
Example #15
0
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
        })
Example #16
0
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)
Example #17
0
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)
Example #18
0
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)
Example #19
0
 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
Example #21
0
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')})
Example #22
0
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')})
Example #23
0
    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)
Example #24
0
    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)
Example #25
0
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})
Example #26
0
 def my_addons(self, n=8):
     """Returns n addons"""
     qs = order_by_translation(self.addons, 'name')
     return qs[:n]
Example #27
0
 def filter_name(self):
     return order_by_translation(self.base_queryset.all(), 'name')
Example #28
0
 def filter_name(self):
     return order_by_translation(self.base_queryset, 'name')
Example #29
0
 def my_addons(self, n=8):
     """Returns n addons"""
     qs = order_by_translation(self.addons, 'name')
     return qs[:n]