Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I turn off column sorting in Django-admin tables or specify WHICH columns are sortable?

Is there an easy way to turn off sortability for for some/all columns in the django admin and/or specify which columns are sortable?

I know I can manually disable sorting via javascript, but that's kinda hacky, and I was hoping there was a better or built-in way.

I'm trying to implement drag/drop ordering of admin lists similar to this: http://djangosnippets.org/snippets/2870/, but it doesn't make sense to have drag/drop ordering if the table is sorted by other-than the position column. The table I'm doing this for will never be a large table, so there's no reason a user would ever need to sort by other-than the position column, and allowing it to sort by another column would just add confusion.

like image 556
Troy Avatar asked Dec 12 '22 14:12

Troy


2 Answers

For those who come here to find out other solutions than prescribed in the above, If your Admin Model Class has a subclass of ModelAdmin or admin.ModelAdmin, there's a subclass variable that can be referred to filter out or to indicate which fields that can be opted for sorting data in columns.

Here's the documentation link.

But here's the content so far.

ModelAdmin.sortable_by
By default, the change list page allows sorting by all model fields (and callables that have the admin_order_field property) specified in list_display.

If you want to disable sorting for some columns, set sortable_by to a collection (e.g. list, tuple, or set) of the subset of list_display that you want to be sortable. An empty collection disables sorting for all columns.
If you need to specify this list dynamically, implement a get_sortable_by() method instead.

Application

  • For instance, we don't want to provide sorting to associateId because of various reasons. To avoid sorting on a particular field. Just exclude that field and re-declare other fields.
class AssociateAttributeFields(ModelAdmin):
    list_display = (
        "associateId",
        "isAllowed",
        "staffRole",
        "dtCreated",
    )
    sortable_by = (
        "isAllowed",
        "staffRole",
        "dtCreated",
    )
    # Can also be the following to avoid being redundant...
    # sortable_by = list_display[1:]

Output For clarity purposes. Demo

like image 160
CodexLink Avatar answered Dec 22 '22 17:12

CodexLink


I have done this by replacing the field name in the list_display tuple with the name of a method which I then implement on the model. For example, to disable sorting on the "title" field on your model, instead of doing this in "admin.py":

class FooAdmin(admin.ModelAdmin):
    list_display = ('title')

use this:

class FooAdmin(admin.ModelAdmin):
    list_display = ('title_for_admin')

Then in your "models.py":

class Foo(models.Model):
    title = models.CharField(max_length=255)

    def title_for_admin(self):
        return self.title

    # To keep 'Title' as the column header in the admin
    title_for_admin.short_description = "Title"

This should produce an admin with the "Title" column as normal, but it is no longer sortable.

This is not a great solution for disabling sorting on all columns or even on many columns if your model has a lot of fields, but it works all right for disabling sorting on one or two columns.

like image 40
nttaylor Avatar answered Dec 22 '22 15:12

nttaylor