Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preferred way to make django-parler fields sortable in admin

I'm using django-parler on several models. Usually, you apply parler to fields like title, name etc and of course you would want to be able to sort these in the Django admin. The closest I've come to do this is by overriding the queryset method on the ModelAdmin, but it seems like an awfully crude way to do it. Also, it only sets the default sorting and you can't click-header-sort the field.

class MyModelAdmin(TranslatableAdmin):
    list_display = ['title', 'language_column']

    def get_queryset(self, request):
        language_code = settings.LANGUAGE_CODE
        qs = Grant.objects.translated(language_code).order_by('translations__title')
        return qs

So the question is: Can you make translated fields sortable in the admin? And it doesn't matter if you have to show or hardcode it only to the default language since it's only used by administrators.

like image 899
mistalaba Avatar asked Feb 10 '23 07:02

mistalaba


1 Answers

This is an area where we're struggling as well. Your example is quite suitable for sorting, as you limit the list to a single language using .translated(..).

To sort things, you can follow the standard ModelAdmin logic, where the list is filtered:

class MyAdmin(TranslatableAdmin):
    list_display = ('title_column', ...)

    def title_column(self, object):
        return object.title
    title_column.short_description = _("Title")
    title_column.admin_order_field = "translations__title"

    def get_queryset(self, request):
        # Limit to a single language!
        language_code = self.get_queryset_language(request)
        return super(MyAdmin, self).get_queryset(request).translated(language_code)

Note that this code currently hides all objects that aren't translated!


With the regular queryset, using .order_by('translations__title') won't work because you could either hit the translated or fallback row first. Such a thing could only be achieved with custom SQL. For example:

SELECT project.id,
       translation.language_code,
       translation.title,
       fallback.title,
       COALESCE(translation.title, fallback.title) AS order_title
FROM "myapp_project" AS project
LEFT OUTER JOIN "myapp_project_translation" AS translation ON (translation.master_id = project.id AND translation.language_code = 'nl')
LEFT OUTER JOIN "myapp_project_translation" AS fallback ON (fallback.master_id = project.id AND fallback.language_code = 'en')
ORDER BY order_title

With a mix of .extra() and admin_order_field you might be able to get this to work, but using .translated() surely makes things easier.

like image 72
vdboor Avatar answered Mar 08 '23 06:03

vdboor