简体   繁体   中英

django admin - how to implement a custom field sort

Let's say I have a data model like so: Apple->Fruit->Organic

so Apple has a foreign key to Fruit... and Organic has 3 fields: name, title, level. I'm displaying the 3 fields in a single column as name_title_level. I want to be able to sort the result by clicking on the table header. I've looked at: https://djangosnippets.org/snippets/2110/ and tried it:

class SpecialOrderingChangeList(ChangeList):
    def apply_special_ordering(self, queryset):
        order_type, order_by = [self.params.get(param, None) for param in ('ot', 'o')]
        special_ordering = self.model_admin.special_ordering
        if special_ordering and order_type and order_by:
            try:
                order_field = self.list_display[int(order_by)]
                ordering = special_ordering[order_field]
                if order_type == 'desc':
                    ordering = ['-' + field for field in ordering]
                queryset = queryset.order_by(*ordering)
            except IndexError:
                return queryset
            except KeyError:
                return queryset
        return queryset

    def get_query_set(self):
        queryset = super(SpecialOrderingChangeList, self).get_query_set()
        queryset = self.apply_special_ordering(queryset)
        return queryset

@admin.register(Apple)
class AppleAdmin(admin.ModelAdmin):
    list_display = ('x', 'get_name')

    def get_name(self, obj):
        return "{}_{}_{}".format(obj.fruit.organic.name,\
            obj.fruit.organic.title, obj.fruit.organic.level)

    special_ordering = {'name': ('fruit__organic__name', 'fruit__organic__title', 'fruit__organic__level')}

    def get_changelist(self, request, **kwargs):
        return SpecialOrderingChangeList

I'm not getting any error and the sort feature is not doing anything. The get_query_set method is not being called. Does anyone know how to do this?


Updates: Here is the updated code. Now the method gets called but still there is no sorting functionality. I mean there is no link in the header at all.

models.py:

from django.db import models

class Organic(models.Model):
    name = models.CharField(max_length=30)
    title = models.CharField(max_length=30)
    label = models.CharField(max_length=30)
    def __unicode__(self):
        return self.name

class Fruit(models.Model):
    organic = models.ForeignKey(Organic)
    def __unicode__(self):
        return self.organic.name

class Apple(models.Model):
    fruit = models.ForeignKey(Fruit)
    color = models.CharField(max_length=30)
    def __unicode__(self):
        return self.color

admin.py:

from django.contrib import admin
from .models import *
from django.contrib.admin.views.main import ChangeList

@admin.register(Organic)
class OrganicAdmin(admin.ModelAdmin):
    pass

@admin.register(Fruit)
class FruitAdmin(admin.ModelAdmin):
    pass


class SpecialOrderingChangeList(ChangeList):
    def apply_special_ordering(self, queryset):
        order_type, order_by = [self.params.get(param, None) for param in ('ot', 'o')]
        special_ordering = self.model_admin.special_ordering
        if special_ordering and order_type and order_by:
            try:
                order_field = self.list_display[int(order_by)]
                ordering = special_ordering[order_field]
                if order_type == 'desc':
                    ordering = ['-' + field for field in ordering]
                queryset = queryset.order_by(*ordering)
            except IndexError:
                return queryset
            except KeyError:
                return queryset
        return queryset

    def get_queryset(self, request):
        queryset = super(SpecialOrderingChangeList, self).get_queryset(request)
        queryset = self.apply_special_ordering(queryset)
        return queryset


@admin.register(Apple)
class AppleAdmin(admin.ModelAdmin):
    list_display = ('color', 'get_name')

    def get_name(self, obj):
        return "{}_{}_{}".format(obj.fruit.organic.name,\
            obj.fruit.organic.title, obj.fruit.organic.label)

    special_ordering = {'name': ('fruit__organic__name', 'fruit__organic__title', 'fruit__organic__label')}

    def get_changelist(self, request, **kwargs):
        return SpecialOrderingChangeList

it should be

get_queryset()

not

get_query_set()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM