Django hvad query translatableModel

ghz 12hours ago ⋅ 7 views

I am using Hvad to make translatable models but I am getting an error trying to fetch a model.

I have two models classes like these:

class Boy(TranslatableModel):
  age = models.PositiveSmallIntegerField()
  toy = models.ForeignKey(Toy)

  translations = TranslatedFields(
    name = models.CharField(max_length=60),
 ) 


class Toy(TranslatableModel):
   price = models.PositiveSmallIntegerField()

   translations = TranslatedFields(
    model_name = models.CharField(max_length=60),
   )

I am trying to do make a query like:

 Boy = Boy.objects.language('en').filter(name="john", toy__model_name="car")

I am getting the following error: To access translated fields like 'model_name' from an untranslated model, you must use a translation aware manager. For non-translatable models, you can get one using hvad.utils.get_translation_aware_manager. For translatable models, use the language() method.

The following works perfect:

 Boy = Boy.objects.language('en').filter(name="john")

So the error is when I add // toy__model_name="car" //

What am I doing wrong? What is the way to achieve what I want?

Answer

The error you're seeing occurs because the field model_name is part of the Toy model's translated fields, which are not directly available for filtering without using a translation-aware manager or method. In your query, you are trying to filter on a translated field (model_name) of a related model (Toy), but you haven't made the related model (Toy) translation-aware in the query.

To filter across translated fields from related models, you need to ensure that the related model's translated fields are also considered translation-aware. Here’s how you can modify your query to handle this:

Solution: Use language() on the related model

You can use language() to ensure that the related Toy model is also considered in the correct language context.

Here’s how you can modify your query:

Boy.objects.language('en').filter(name="john", toy__translations__model_name="car")

Explanation:

  1. toy__translations__model_name:

    • Since model_name is a translated field in the Toy model, you need to access it through translations__model_name.
    • The translations attribute is a manager that handles the translation-related fields, so you need to reference the translated field (model_name) through it.
  2. language('en'):

    • You've already used .language('en') on the Boy model to fetch the English translations for name, and similarly, by referencing the translated fields of Toy through translations, Django knows to fetch the translation of model_name in the appropriate language.

Full Example Query:

This query will fetch Boy objects whose translated name is "john" and whose related Toy object's translated model_name is "car" in the English language.

Boy.objects.language('en').filter(name="john", toy__translations__model_name="car")

Why the Error Occurred:

  • Related model's translated field: In your initial query, toy__model_name was incorrectly referring to the untranslated Toy model field. Since model_name is a translated field, it requires accessing it through the translations manager.
  • Translation-awareness: The error message suggests that you need to use translation-aware methods to access translated fields in related models. The translations manager on Toy enables that.

Additional Notes:

  • If you're doing complex queries with multiple languages and translations, always ensure that any field you are filtering or accessing is wrapped with the translations manager when it's a translated field.