KristianOellegaard / django-hvad

Painless translations in django, using the regular ORM. Integrates easily into existing projects and apps. Easy convertible from django-multilingual-ng.
https://github.com/KristianOellegaard/django-hvad
Other
533 stars 128 forks source link

Filtering foreign key translatable field #214

Closed psychok7 closed 9 years ago

psychok7 commented 9 years ago

So i have a model that has a foreign key to another (translatable model) called mission. i have:

    user_language = self.request.GET.get('language')
    women = Women.objects.language(user_language).all()

I want to do something like this: women.filter(mission__mission='something') but i get a :

*** WrongManager: To access translated fields like 'mission' 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.

I have tried using women = get_translation_aware_manager(Women).all() instead but then i dont know how to activate translations in case i want to search a mission in english or french.

My models are:

class UserProfile(models.Model):
    mission = models.ForeignKey(
        'core.Mission', blank=True, null=True, help_text="User's Mission",
        related_name='user_profiles_missions'
    )
class Women(TranslatableModel, UserProfile):
    pass

class Mission(TranslatableModel):
    translations = TranslatedFields(
        mission=models.CharField(max_length=255, help_text="Mission name"),
    )

    def __unicode__(self):
        return self.lazy_translation_getter('mission', str(self.pk))

How can i filter using translations across my foreign key field ? thanks

spectras commented 9 years ago

Hello,

psychok7 commented 9 years ago

@spectras woman is translatable i just didn't think the fields were relevant. here is the full model:

class Women(TranslatableModel, UserProfile):
    translations = TranslatedFields(
        position=models.CharField(
            max_length=255, blank=True,
            help_text="Woman's position. Ex. 'Young Graduate Trainee'"
        ),
        nationality=models.CharField(
            max_length=30, blank=True, help_text="Woman's nationality"
        ),
)
type=models.CharField()

What is the correct way for me to deal with this then?
spectras commented 9 years ago

Fields are not relevant indeed, but I had to be sure there were some. Alright. So, unfortunately, filtering on translations of a related model is not supported yet. This is because filter translation only handles one level depth at the moment. Work in progress in #196 aims at making it happen. In the meantime you can either do the query in two steps, or dig into hvad internals:

# In two steps
missions = Mission.objects.language(user_language).filter(mission='something')
women = Women.objects.language(user_language).filter(mission__in=missions)

# In one step, but using some hvad internals
women = Women.objects.language(user_language).filter(
    mission__translations__language_code=user_language,
    mission__translations__mission='something'
)
# (basically, this is the query that hvad would generate if it supported deep filters)

I would recommend first option if your db engine is good at subqueries. On PostgreSQL, for instance, performance would be same as second option, but code does not rely on hvad internals.

This limitation to shallow filters in the translation engine is one of the two big issues to tackle before we go from alpha to beta status (the other being translatable fields in admin).

psychok7 commented 9 years ago

@spectras thanks for your support, first option fixed my problems

spectras commented 9 years ago

You're welcome. I really hope to have full, deep translation support working by the end of the year, but there are some issues with queries that filter twice on the same relation. Anyway, if you have ideas for improvements while using hvad, in the code or in the documentation, please feel free to open suggestions here.