Search code examples
pythondjangodjango-modeltranslation

language independent query with django-modeltranslation


I currently started to use django-modeltranslation in a Django app and I would like to make a query to retrieve the instance of a model, independent of the language set in the system. For example I have the following model:

class Product(models.Model):
    description = models.CharField(max_length=200)
    sku = models.CharField(unique=True, null=False, max_length=30)
    price = models.DecimalField(max_digits=8, decimal_places=2)

and the following in translation.py:

class ProductTranslationOptions(TranslationOptions):
    fields = ('description', 'sku')

translator.register(Product, ProductTranslationOptions)

and the Django setting:

gettext = lambda s: s
LANGUAGES = (
    ('en', gettext('English')),
    ('de', gettext('German')),
)

MODELTRANSLATION_LANGUAGES = ('en', 'de')
MODELTRANSLATION_DEFAULT_LANGUAGE = 'en'

MODELTRANSLATION_FALLBACK_LANGUAGES = ('en',)

Let's create a product instance:

Product.objects.create(description_en='product en', description_de='product de', sku_en='sku-001', sku_de='sku-002', price=10.0)

Now I want to find the instance with the sku sku-002, to retrieve the price of a product (which is independent of the language).

Product.objects.filter(sku='sku-002') 

However this returns an empty MultilingualQuerySet. Only the following returns the correct Product instance.

Product.objects.filter(sku_de='sku-002') 

or

from django.utils import translation
translation.activate('de')  
Product.objects.filter(sku='sku-002') 

I guess this is the intended behavior of django-modeltranslation, but sometimes it would be practical to find an instance independent of the language.

A solution could be to iterate through all LANGUAGES and try to find the instance for each language:

from django.conf import settings

LANGUAGES = list(getattr(settings,
                'MODELTRANSLATION_LANGUAGES',
                (l[0] for l in settings.LANGUAGES)))   

def find_product_by_sku(sku):
    for language in LANGUAGES:
        product = Product.objects.filter(**{"sku_{}".format(language): sku})
        if product:
           return product

However this is not very practical, especially for an existing application, where the code would need to be adjusted in several places. Is there a way to use directly the Query Set Manager to retrieve the instance independent of the language?


Solution

  • See here: https://stackoverflow.com/questions/27418377/django-modeltranslation-queries-fallback It looks like a current behaviour (no support for fallback during queries). In the stackoverflow link is this recommended which could help a little: .filter(Q(title_de = 'hello') | Q(title_en = 'hello'))

    You could take a look if packages which use postgres jsonb field for all languages together (django-modeltrans, django-nece) support this better. I have tested nothing, but I read at django-modeltrans about "_i18n" and about other support in django-nece.