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).