hvad.manager
¶
This module is where most of the functionality is implemented.
-
hvad.manager.
FALLBACK_LANGUAGES
¶ The default sequence for fallback languages, populates itself from
settings.LANGUAGES
, could possibly become a setting on it’s own at some point.
FieldTranslator¶
-
class
hvad.manager.
FieldTranslator
¶ The cache mentioned in this class is the instance of the class itself, since it inherits dict.
Possibly this class is not feature complete since it does not care about multi-relation queries. It should probably use
hvad.fieldtranslator.translate()
after the first level if it hits the Shared Model.てz-
get
(self, key)¶ Returns the translated fieldname for key. If it’s already cached, return it from the cache, otherwise call
build()
-
build
(self, key)¶ Returns the key prefixed by
'master__'
if it’s a shared field, otherwise returns the key unchanged.
-
ValuesMixin¶
-
class
hvad.manager.
ValuesMixin
¶ A mixin class for
ValuesQuerySet
which implements the functionality needed byTranslationQueryset.values()
andTranslationQueryset.values_list()
.-
_strip_master
(self, key)¶ Strips
'master__'
from the key if the key starts with that string.
-
iterator
(self)¶ Iterates over the rows from the superclass iterator and calls
_strip_master()
on the key if the row is a dictionary.
-
SkipMasterSelectMixin¶
-
class
hvad.manager.
SkipMasterSelectMixin
¶ A mixin class for specialized querysets such as
DateQuerySet
andDateTimeQuerySet
which forcesTranslationQueryset
not to add the related lookup on the master field. This is required as those specialized querysets use DISTINCT, and added the related lookup brings along all fields on the Shared Model, breaking the lookup.
TranslationQueryset¶
-
class
hvad.manager.
TranslationQueryset
¶ Any method on this queryset that returns a model instance or a queryset of model instances actually returns a Translations Model which gets combined to behave like a Shared Model. While this manager is on the Shared Model, it is actually a manager for the Translations Model since the model gets switched when this queryset is instantiated from the
TranslationManager
.-
override_classes
¶ A dictionary of django classes to hvad classes to mixin when
_clone()
is called with an explicit klass argument.
-
_local_field_names
¶ A list of field names on the Shared Model.
-
_field_translator
¶ The cached field translator for this manager.
-
_language_code
¶ The language code of this queryset, or one of the following special values:
None
:get_language()
will be called to get the current language.'all'
: no language filtering will be applied, a copy of an instance will be returned for every translation that matched the query.
-
_language_fallbacks
¶ A tuple of fallbacks used for this queryset, if fallbacks have been activated by
fallbacks()
, or None otherwise.A
None
value in the tuple will be replaced with current language at query evaluation.
-
_hvad_switch_fields
¶ A tuple of attributes to move from the Translations Model to the Shared Model instance before returning objects to the caller. It is mostly used by
extra()
so additional values collected by theselect
argument are available on the final instance.
-
translations_manager
¶ The (real) manager of the Translations Model.
The Shared Model.
-
field_translator
¶ The field translator for this manager, sets
_field_translator
if it’sNone
.
Returns a list of field names on the Shared Model, sets
_local_field_names
if it’sNone
.
-
_translate_args_kwargs
(self, *args, **kwargs)¶ Translates args (
Q
objects) and kwargs (dictionary of query lookups and values) to be language aware, by prefixing fields on the Shared Model with'master__'
. Usesfield_translator
for the kwargs and_recurse_q()
for the args. Returns a tuple of translated args and translated kwargs.
-
_translate_fieldnames
(self, fieldnames)¶ Translate a list of fieldnames by prefixing fields on the Shared Model with
'master__'
usingfield_translator
. Returns a list of translated fieldnames.
-
_recurse_q
(self, q)¶ Recursively walks a
Q
object and translates it’s query lookups to be prefixed by'master__'
if they access a field on Shared Model.Every
Q
object has an attributechildren
which is either a list of otherQ
objects or a tuple where the key is the query lookup.This method returns a new
Q
object.
-
_find_language_code
(self, q)¶ Searches a
Q
object for language code lookups. If it finds a childQ
object that defines a language code, it returns that language code if it’s notNone
. Used inget()
to ensure a language code is defined.For more information about
Q
objects, see_recurse_q()
.Returns the language code if one was found or
None
.
-
_split_kwargs
(self, **kwargs)¶ Splits keyword arguments into two dictionaries holding the shared and translated fields.
Returns a tuple of dictionaries of shared and translated fields.
-
_get_class
(self, klass)¶ Given a
QuerySet
class or subclass, it checks if the class is a subclass of any class inoverride_classes
and if so, returns a new class which mixes the initial class, the class fromoverride_classes
andTranslationQueryset
. Otherwise returns the class given.
Returns a clone of this queryset but for the shared model. Does so by creating a
QuerySet
onshared_model
and filtering over this queryset. Returns a queryset for the Shared Model.
-
_add_language_filter
(self)¶ Apply the language filter to current query. Language is retrieved from
_language_code
, orget_language()
if None. Iffallbacks()
have been set, apply the additional join as well.Special value
'all'
will prevent any language filter from being applied, resulting in the query considering all translations, possibly returning the same instance mutiple times if several of its translations match. In that case, each instance will becombined
with one of the matching translations.Applied filters include the base language filter on the language_code field, as well as any related model translation set up by
select_related()
.
New in version 0.5.
Applies the related selections to current query. This includes the basic selection of
master
, any relation specified throughselect_related()
and the translations of any translatable models it navigates through.
-
language
(self, language_code=None)¶ Specifies a language for this queryset. This sets the
_language_code
, but no filter are actually applied until_add_language_filter()
is called. This allows for query-time resolution of the None value. It is an error to calllanguage()
multiple times on the same queryset.The following special values are accepted:
None
, or no value:get_language()
will be called to get the current language.'all'
: no language filtering will be applied, a copy of an instance will be returned for every translation that matched the query, each copy beingcombined
with one of the matching translations.
Returns a queryset.
Note
Support for using
language('all')
andselect_related()
on the same queryset is experimental. Please check the generated queries and open an issue if you have any problem. Feedback is appreciated as well.
-
fallbacks
(self, *languages)¶ New in version 0.6.
Activates fallbacks for this queryset. This sets the
_language_fallbacks
attribute, but does not apply any join or filtering until_add_language_filter()
is called. This allows for query-time resolution of theNone
values in the list.The following special cases are accepted:
None
as a single argument will disable fallbacks on the queryset.- An empty argument list will use
LANGUAGES
setting as a fallback list. - A
None
value a language will be replaced by the current language at query evalution time, by callingget_language()
Returns a queryset.
Note
Using
fallbacks
andselect_related()
on the same queryset is not supported and will raise aNotImplementedError
.Note
This feature requires Django 1.6 or newer.
-
create
(self, **kwargs)¶ Creates a new instance using the kwargs given. If
_language_code
is not set and language_code is not in kwargs, it usesget_language()
to get the current language and injects that into kwargs.This causes two queries as opposed to the one by the normal queryset.
Returns the newly created (combined) instance.
Note
It is an error to call
create
with nolanguage_code
on a queryset whose_language_code
is'all'
. Doing so will raise aValueError
.
-
bulk_create
(self, objs, batch_size=None)¶ Not implemented yet and unlikely to be due to inherent limitations of multi-table inserts.
-
update_or_create
(self, defaults=None, **kwargs)¶ Not implemented yet.
-
get
(self, *args, **kwargs)¶ Gets a single instance from this queryset using the args and kwargs given. The args and kwargs are translated using
_translate_args_kwargs()
.If a language code is given in the kwargs, it calls
language()
using the language code provided. If none is given in kwargs, it uses_find_language_code()
on theQ
objects given in args. If no args were given or they don’t contain a language code, it searches thedjango.db.models.sql.where.WhereNode
objects on the current queryset for language codes. If none was found, it will use the language of this queryset from_language_code
, or the current language as returned byget_language()
of that is None.Returns a (combined) instance if one can be found for the filters given, otherwise raises an appropriate exception depending on whether no or multiple objects were found.
Warning
It is an error to pass language_code in a Q object if a
select_related()
clause was enabled on this queryset. Doing so will raise anAssertionError
.
-
get_or_create
(self, **kwargs)¶ Will try to fetch the translated instance for the kwargs given.
If it can’t find it, it will try to find a shared instance (using
_splitkwargs()
). If it finds a shared instance, it will create the translated instance. If it does not find a shared instance, it will create both.Returns a tuple of a (combined) instance and a boolean flag which is
False
if it found the instance orTrue
if it created either the translated or both instances.
-
filter
(self, *args, **kwargs)¶ Translates args and kwargs using
_translate_args_kwargs()
and calls the superclass using the new args and kwargs.
-
aggregate
(self, *args, **kwargs)¶ Loops through the passed aggregates and translates the fieldnames using
_translate_fieldnames()
and calls the superclass
-
latest
(self, field_name=None)¶ Translates the fieldname (if given) using
field_translator
and calls the superclass.
-
earliest
(self, field_name=None)¶ New in version 0.4.
Translates the fieldname (if given) using
field_translator
and calls the superclass.Only defined if django version is 1.6 or newer.
-
in_bulk
(self, id_list)¶ New in version 0.4.
Retrieves the objects, building a dict from
iterator()
.
-
delete
(self)¶ Deletes the Shared Model using
_get_shared_queryset()
.
-
delete_translations
(self)¶ Deletes the translations (and only the translations) by first breaking their relation to the Shared Model and then calling the delete method on the superclass. This uses two queries.
-
update
(self, **kwargs)¶ Updates this queryset using kwargs. Calls
_split_kwargs()
to get two dictionaries holding only the shared or translated fields respectively. If translated fields are given, calls the superclass with the translated fields. If shared fields are given, uses_get_shared_queryset()
to update the shared fields.If both shared and translated fields are updated, two queries are executed, if only one of the two are given, one query is executed.
Returns the count of updated objects, which if both translated and shared fields are given is the sum of the two update calls.
-
values
(self, *fields)¶ Translates fields using
_translate_fieldnames()
and calls the superclass.
-
values_list
(self, *fields, **kwargs)¶ Translates fields using
_translate_fieldnames()
and calls the superclass.
-
dates
(self, field_name, kind, order='ASC')¶ Translates fields using
_translate_fieldnames()
and calls the superclass.
-
datetimes
(self, field_name, *args, **kwargs)¶ Translates fields using
_translate_fieldnames()
and calls the superclass.Only defined if django version is 1.6 or newer.
-
complex_filter
(self, filter_obj)¶ Not really implemented yet, but if filter_obj is an empty dictionary it just returns this queryset, since this is required to get admin to work.
-
annotate
(self, *args, **kwargs)¶ Not implemented yet.
-
order_by
(self, *field_names)¶ Translates fields using
_translate_fieldnames()
and calls the superclass.
-
reverse
(self)¶ Calls the superclass.
-
defer
(self, *fields)¶ Not implemented yet.
-
only
(self, *fields)¶ Not implemented yet.
-
_clone
(self, klass=None, setup=False, **kwargs)¶ Injects _local_field_names, _field_translator, _language_code, and shared_model into kwargs. If a klass is given, calls
_get_class()
to get a mixed class if necessary.Calls the superclass with the new kwargs and klass.
-
iterator
(self)¶ Iterates using the iterator from the superclass, if the objects yielded have a master, it yields a combined instance, otherwise the instance itself to enable non-cascading deletion.
Interestingly, implementing the combination here also works for
get()
and__getitem__()
. This is because the former uses the latter, which in turn fetches results from an iterator.
-
TranslationManager¶
-
class
hvad.manager.
TranslationManager
¶ Manager to be used on
hvad.models.TranslatableModel
.-
translations_model
¶ The Translations Model for this manager.
-
queryset_class
¶ The QuerySet for this manager, used by the
language()
method. Overwrite to use a custom queryset. Your custom queryset class must inheritTranslationQueryset
. Defaults toTranslationQueryset
.
-
fallback_class
¶ The QuerySet for this manager, used by the
untranslated()
method. Overwrite to use a custom queryset. Defaults toFallbackQueryset
.
-
default_class
¶ The QuerySet for this manager, used by the
get_queryset()
method and generally any query that does not invoke eitherlanguage()
oruntranslated()
. Overwrite to use a custom queryset. Defaults toQuerySet
.
-
language
(self, language_code=None)¶ Instanciates a
TranslationQueryset
fromqueryset_class
and callsTranslationQueryset.language()
on that queryset. This type of queryset will filter by language, returning only objects that have a translation in the specified language. Translated fields will be available on the objects, in the specified language.
-
untranslated
(self)¶ Returns an instance of
FallbackQueryset
for this manager, or any custom queryset defined byfallback_class
. This type of queryset will load translations using fallbacks if current language is not available. It can generate a lot a queries, use with caution.
-
get_queryset
(self)¶ Returns a vanilla, non-translating queryset for this manager. It uses the default
QuerySet
or any custom queryset defined bydefault_class
.Instances returned will not have translated fields, and attempts to access them will result in an exception being raised. See
language()
anduntranslated()
to access translated fields.It is possible to override this behavior by setting
default_class
toTranslationQueryset
,FallbackQueryset
or any queryset that has a translation-aware implementation.
-
contribute_to_class
(self, model, name)¶ Contributes this manager onto the class.
-
FallbackQueryset¶
-
class
hvad.manager.
FallbackQueryset
¶ Deprecated since version 1.4.
A queryset that can optionally use fallbacks and by default only fetches the Shared Model.
There are actually two underlying implementations, the
LegacyFallbackQueryset
and theSelfJoinFallbackQueryset
. Implementation is chosen at initialization based on theHVAD_LEGACY_FALLBACKS
setting. It defaults toFalse
(use SelfJoin) on Django 1.6 and newer, andTrue
(use Legacy) on older versions.The
LegacyFallbackQueryset
generates lots of queries as it walks through batches of models, fetches their translations and matches them onto the models.The
SelfJoinFallbackQueryset
uses a single self outer join to achieve the same result in only one (complex) query. Performance is good as the number of items per model in the cross-product is limited to the number of languages that Django supports. Implementation digs deeper into Django internals, though.-
_translation_fallbacks
¶ List of fallbacks to use (or
None
).
-
iterator
(self)¶ If
_translation_fallbacks
is set, it iterates using the superclass and tries to get the translation using the order of language codes defined in_translation_fallbacks
. As soon as it finds a translation for an object, it yields a combined object using that translation. Otherwise yields an uncombined object. Due to the way this works, it can cause a lot of queries and this should be improved if possible.If no fallbacks are given, it just iterates using the superclass.
-
use_fallbacks
(self, *fallbacks)¶ Deprecated since version 1.4.
If this method gets called,
iterator()
will use the fallbacks defined here. None value will be replaced with current language at query evaluation, as returned byget_language()
. If not fallbacks are given,FALLBACK_LANGUAGES
will be used, with current language prepended.This method has been superseded by
fallbacks()
and will be removed when support for Django 1.4 is dropped.
-
_clone
(self, klass=None, setup=False, **kwargs)¶ Injects translation_fallbacks into kwargs and calls the superclass.
-
TranslationAwareQueryset¶
-
class
hvad.manager.
TranslationAwareQueryset
¶ -
_language_code
¶ The language code of this queryset.
-
_translate_args_kwargs
(self, *args, **kwargs)¶ Calls
language()
using_language_code
as an argument.Translates args and kwargs into translation aware args and kwargs using
hvad.fieldtranslator.translate()
by iterating over the kwargs dictionary and translating it’s keys and recursing over theQ
objects in args using_recurse_q()
.Returns a triple of newargs, newkwargs and extra_filters where newargs and newkwargs are the translated versions of args and kwargs and extra_filters is a
Q
object to use to filter for the current language.
-
_recurse_q
(self, q)¶ Recursively translate the keys in the
Q
object given usinghvad.fieldtranslator.translate()
. For more information aboutQ
, seeTranslationQueryset._recurse_q()
.Returns a tuple of q and language_joins where q is the translated
Q
object and language_joins is a list of extra language join filters to be applied using the current language.
-
_translate_fieldnames
(self, fields)¶ Calls
language()
using_language_code
as an argument.Translates the fieldnames given using
hvad.fieldtranslator.translate()
Returns a tuple of newfields and extra_filters where newfields is a list of translated fieldnames and extra_filters is a
Q
object to be used to filter for language joins.
-
language
(self, language_code=None)¶ Sets the
_language_code
attribute either to the language given with language_code or by getting the current language fromget_language()
. UnlikeTranslationQueryset.language()
, this does not actually filter by the language yet as this happens in_filter_extra()
.
-
get
(self, *args, **kwargs)¶ Gets a single object from this queryset by filtering by args and kwargs, which are first translated using
_translate_args_kwargs()
. Calls_filter_extra()
with the extra_filters returned by_translate_args_kwargs()
to get a queryset from the superclass and to call that queryset.Returns an instance of the model of this queryset or raises an appropriate exception when none or multiple objects were found.
-
filter
(self, *args, **kwargs)¶ Filters the queryset by args and kwargs by translating them using
_translate_args_kwargs()
and calling_filter_extra()
with the extra_filters returned by_translate_args_kwargs()
.
-
aggregate
(self, *args, **kwargs)¶ Not implemented yet.
-
latest
(self, field_name=None)¶ If a fieldname is given, uses
hvad.fieldtranslator.translate()
to translate that fieldname. Calls_filter_extra()
with the extra_filters returned byhvad.fieldtranslator.translate()
if it was used, otherwise with an emptyQ
object.
-
in_bulk
(self, id_list)¶ Not implemented yet
-
values
(self, *fields)¶ Calls
_translate_fieldnames()
to translated the fields. Then calls_filter_extra()
with the extra_filters returned by_translate_fieldnames()
.
-
values_list
(self, *fields, **kwargs)¶ Calls
_translate_fieldnames()
to translated the fields. Then calls_filter_extra()
with the extra_filters returned by_translate_fieldnames()
.
-
dates
(self, field_name, kind, order='ASC')¶ Not implemented yet.
-
exclude
(self, *args, **kwargs)¶ Not implemented yet.
-
complex_filter
(self, filter_obj)¶ Not really implemented yet, but if filter_obj is an empty dictionary it just returns this queryset, to make admin work.
-
annotate
(self, *args, **kwargs)¶ Not implemented yet.
-
order_by
(self, *field_names)¶ Calls
_translate_fieldnames()
to translated the fields. Then calls_filter_extra()
with the extra_filters returned by_translate_fieldnames()
.
-
reverse
(self)¶ Not implemented yet.
-
defer
(self, *fields)¶ Not implemented yet.
-
only
(self, *fields)¶ Not implemented yet.
-
_clone
(self, klass=None, setup=False, **kwargs)¶ Injects _language_code into kwargs and calls the superclass.
-
_filter_extra
(self, extra_filters)¶ Filters this queryset by the
Q
object provided in extra_filters and returns a queryset from the superclass, so that the methods that call this method can directely access methods on the superclass to reduce boilerplate code.Warning
This internal method returns a
super()
proxy object, be sure to understand the implications before using it.
-
TranslationAwareManager¶
-
class
hvad.manager.
TranslationAwareManager
¶ -
get_queryset
(self)¶ Returns an instance of
TranslationAwareQueryset
.
-