Guide: QuerySets

This module provides an in depth knowledge of the Translations querysets.

Important

The examples are assumed to CRUD this dataset.

Type\Lang

English

German

Continent

Europe

Europa

Asia

Asien

Country

Germany

Deutschland

South Korea

Südkorea

City

Cologne

Köln

Seoul

Seul

Please memorize this dataset in order to understand the examples better.

Make querysets translatable

To make a queryset translatable make sure the queryset model is translatable.

Translate the queryset

To translate the queryset in a language use the translate() method. It translates the translatable fields of the queryset in a language in the evaluation. It accepts a language code which determines the language to translate the queryset in.

To translate an instance in a language:

from sample.models import Continent

# translate the instance
europe = Continent.objects.translate('de').get(code='EU')

print(europe)
Europa

To translate a queryset in a language:

from sample.models import Continent

# translate the queryset
continents = Continent.objects.translate('de').all()

print(continents)
<TranslatableQuerySet [
    <Continent: Asien>,
    <Continent: Europa>,
]>

The language code must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Note

Translating only affects the translatable fields that have a translation.

Translate the queryset relations

To translate some queryset relations use the translate_related() method. It translates the translatable fields of the queryset relations in the evaluation. It accepts some relations which determines the queryset relations to translate.

To translate some queryset relations:

from sample.models import Continent

# translate the queryset relations
continents = Continent.objects.translate_related(
    'countries',
    'countries__cities',
).translate('de')

print(continents)
print(continents[0].countries.all())
print(continents[0].countries.all()[0].cities.all())
<TranslatableQuerySet [
    <Continent: Asien>,
    <Continent: Europa>,
]>
<TranslatableQuerySet [
    <Country: Deutschland>,
]>
<TranslatableQuerySet [
    <City: Köln>,
]>

Each relation may be divided into separate parts by __s to represent a deeply nested relation. Each part must be a related_name. The models of the relations must be translatable.

Note

It is recommended for the queryset relations to be prefetched before translating them, in order to reach optimal performance.

To do this use select_related, prefetch_related or prefetch_related_objects.

Warning

Any subsequent chained methods on the relations queryset which imply a database query will reset previously translated results:

from sample.models import Continent

continents = Continent.objects.translate_related(
    'countries',
).translate('de')

# Querying after translation
print(continents[0].countries.exclude(name=''))
<TranslatableQuerySet [
    <Country: Germany>,
]>

In some cases the querying can be done before the translation:

from django.db.models import Prefetch
from sample.models import Continent, Country

# Querying before translation
continents = Continent.objects.prefetch_related(
    Prefetch(
        'countries',
        queryset=Country.objects.exclude(name=''),
    ),
).translate_related(
    'countries',
).translate('de')

print(continents[0].countries.all())
<TranslatableQuerySet [
    <Country: Deutschland>,
]>

And in some cases the querying must be done anyway, in these cases:

from sample.models import Continent

continents = Continent.objects.translate_related(
    'countries',
).translate('de')

# Just `translate` the relation again after querying
print(continents[0].countries.exclude(name='').translate('de'))
<TranslatableQuerySet [
    <Country: Deutschland>,
]>

Probe (filter, exclude, etc.) the queryset

To probe the queryset in some language(s) use the probe() method. It probes the translatable fields of the queryset in a language in the evaluation. It accepts some language code(s) which determines the language(s) to probe the queryset in.

To probe the queryset in a custom language:

from django.db.models import Q
from sample.models import Continent

# probe the queryset
continents = Continent.objects.probe('de').filter(
    Q(name='Europa') | Q(name='Asien'))

print(continents)
<TranslatableQuerySet [
    <Continent: Asia>,
    <Continent: Europe>,
]>

To probe the queryset in multiple custom languages:

from django.db.models import Q
from sample.models import Continent

# probe the queryset
continents = Continent.objects.probe(['en', 'de']).filter(
    Q(name='Europa') | Q(name='Asien')).distinct()

print(continents)
<TranslatableQuerySet [
    <Continent: Asia>,
    <Continent: Europe>,
]>

The language code(s) must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Each query lookup may contain some relations. Each relation may be divided into separate parts by __s to represent a deeply nested relation. Each part must be a related_query_name.

Note

Please note that the results are returned in the default language. To translate them use the translate method.

Note

Probing only affects the translatable fields that have a translation.

Note

Make sure to use distinct on the probed queryset when using multiple languages, otherwise it may return duplicate results.

Advanced querying

To encapsulate translation queries as objects that can then be combined logically (using & and |) use the TQ class. It works just like the normal django Q object untill you specialize it (call its object) in some language(s). It accepts some language code(s) which determines the language(s) to specialize the query in.

To create complex logical combinations of queries for different languages:

from translations.query import TQ
from sample.models import Continent

continents = Continent.objects.filter(
    TQ(
        countries__cities__name__startswith='Cologne',
    )         # use probe language (default English) for this query
    |         # logical combinator
    TQ(
        countries__cities__name__startswith='Köln',
    )('de')   # use German for this query
).distinct()

print(continents)
<TranslatableQuerySet [
    <Continent: Europe>,
]>

The language code(s) must already be declared in the LANGUAGES setting. It is optional and if it is not passed in, it is automatically set to the active language code.

Note

TQ objects act exactly like Q objects, untill they are called using some language(s).