Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

non-lazyness of the <field>_i18n lookup transformation #34

Open
jieter opened this issue Jan 25, 2018 · 2 comments
Open

non-lazyness of the <field>_i18n lookup transformation #34

jieter opened this issue Jan 25, 2018 · 2 comments

Comments

@jieter
Copy link
Member

jieter commented Jan 25, 2018

Lookups are tranformed when the queryset definition is executed, which might be unexpected behavior with querysets.
An problematic use case might be defining the choices for a ModelChoiceField.

from django.utils.translation import override

with override('en'):
    qs = Blog.objects.filter(title_i18n='foo')
    print(str(qs.query))

# SELECT "app_blog"."id", "app_blog"."title", "app_blog"."body", "app_blog"."category_id", "app_blog"."i18n" 
# FROM "app_blog" 
# WHERE "app_blog"."title" = 'foo'

with override('nl'):
    print(str(qs.query))

# same query
    
with override('nl'):
    qs = Blog.objects.filter(title_i18n='foo')
    print(str(qs.query))

# SELECT "app_blog"."id", "app_blog"."title", "app_blog"."body", "app_blog"."category_id", "app_blog"."i18n", COALESCE(("app_blog"."i18n" ->> 'title_nl'), "app_blog"."title") AS "title_i18n_annotation" 
# FROM "app_blog" 
# WHERE COALESCE(("app_blog"."i18n" ->> 'title_nl'), "app_blog"."title") = 'foo'

Using a callable helps, but I'm not sure if the queryset argument of ModelChoiceField supports that:

qs = lambda: Blog.objects.filter(title_i18n='foo')

with override('nl'):
    print(str(qs().query))

# SELECT "app_blog"."id", "app_blog"."title", "app_blog"."body", "app_blog"."category_id", "app_blog"."i18n", COALESCE(("app_blog"."i18n" ->> 'title_nl'), "app_blog"."title") AS "title_i18n_annotation" 
# FROM "app_blog" 
# WHERE COALESCE(("app_blog"."i18n" ->> 'title_nl'), "app_blog"."title") = 'foo'

with override('en'):
    print(str(qs().query))

# SELECT "app_blog"."id", "app_blog"."title", "app_blog"."body", "app_blog"."category_id", "app_blog"."i18n" 
# FROM "app_blog" 
# WHERE "app_blog"."title" = 'foo'
@jieter jieter changed the title lazyness of the <field>_i18n lookup non-lazyness of the <field>_i18n lookup transformation Jan 25, 2018
@pjburon
Copy link

pjburon commented Feb 28, 2018

Hello,

I've noticed also a strange behavior using django.db.models.Q filters, I'm not sure if it's due to the same issue or not:

products = models.Product.objects.filter(
    Q(category__slug_i18n=category_slug) | Q(category__parent__slug_i18n=category_slug), 
    is_active=True
)

Result KO

But different queries without OR operator work fine:

products = models.Product.objects.filter(Q(category__slug_i18n=category_slug) , is_active=True)

Result OK.

products = models.Product.objects.filter(Q(category__parent__slug_i18n=category_slug), is_active=True)

Result OK

So alternative that works:

products = models.Product.objects.filter(category__slug_i18n=category_slug, is_active=True) | 
           models.Product.objects.filter(category__parent__slug_i18n=category_slug, is_active=True)

Result OK

@jieter
Copy link
Member Author

jieter commented Mar 9, 2018

@pjburon thanks for the extra info, I'll have a look next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants