2010-12-30 2 views
2

Показывая модель в list_display администратора Django, я бы хотел отсортировать сначала по одному столбцу, а затем по другому.
Вот пример модели:Django admin: упорядочивание второго уровня в list_display

class Customer(models.Model): 
    name = models.CharField(max_length=30) 
    the_date = models.DateField() 

Как это может быть достигнуто?

ответ

1

Я думаю, что вы ищете атрибут «заказать» класса admin.

http://docs.djangoproject.com/en/1.3/ref/contrib/admin/

Edit: Мой предыдущий ответ неверен. Согласно вышеприведенной документации, Django только чтит первую запись в кортеже. Существует/был a ticket, чтобы решить эту проблему. Существуют и другие предлагаемые решения, которые я также пробовал, но никто из них, похоже, не работал с моей версией Django.

Однако я вернулся к этой проблеме сегодня как часть проекта и, наконец, нашел что-то, что сработало для меня. Мое решение было основано на this Django snippet, и я опубликую здесь код фрагмента для полноты.

from django.contrib import admin 
from django.contrib.admin.views.main import ChangeList 
from tunes.models import Song 

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 

class SongAdmin(admin.ModelAdmin): 
    list_display = ['name', 'time', 'artist', 'album', 'track', 'total_tracks'] 
    special_ordering = {'artist': ('artist', 'album', 'track'), 'album': ('album', 'track')} 

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

admin.site.register(Song, SongAdmin) 
+0

Nope. Документация Django говорит о заказе: «Django будет соблюдать только первый элемент в списке/кортеже, любые другие будут проигнорированы». – Jonathan

+0

Хорошо пятнистый. Забавно, я использовал это много раз, полагая, что, поскольку это был кортеж, он упорядочивал все столбцы. Наверное, я никогда не замечал, что это не так! В этом случае, я думаю, нам пришлось бы переопределить метод queryset() ModelAdmin модели, чтобы изменить порядок сортировки. – bogeymin

+0

Я тоже это пробовал, и это не помогло.Если вам удастся добиться успеха в этом направлении, не могли бы вы разместить свой код? – Jonathan

0

Это основано на 1-м отредактированном ответе bogeyman, но разбит на существенную функцию.

В моей models.py определить ordering в моделях Meta как обычно:

class Customer(models.Model): 
    name = models.CharField(max_length=30) 
    the_date = models.DateField() 

    class Meta: 
     ordering = ('the_date', 'name') # sort by date then name. 

Затем в admin.py подкласса ChangeList, но заставить query_set в конечном счете быть отсортированы по упорядочению, указанных в Meta из модель.

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


class SpecialOrderingChangeList(ChangeList): 
    def get_query_set(self): 
     queryset = super(SpecialOrderingChangeList, self).get_query_set() 
     return queryset.order_by(*self.model._meta.ordering) 

class CustomerAdmin(admin.ModelAdmin): 
    def get_changelist(self, request, **kwargs): 
     return SpecialOrderingChangeList 

admin.site.register(Customer, CustomerAdmin) 

Если вы предпочитаете определять порядок в ModelAdmin; вы можете это сделать; просто измените return queryset.order_by(*self.model._meta.ordering) на return queryset.order_by(*self.model_admin.ordering) и добавьте список, определяющий ordering = ['the_date', 'name'] в CustomerAdmin.

0

Вы можете достичь этого, используя ствол Django, а не 1,3

https://docs.djangoproject.com/en/dev/ref/contrib/admin/

Новое в версии Django развития.

Если вам необходимо указать динамический заказ (например, в зависимости от пользователя или языка), вы можете реализовать метод get_ordering() .

Изменено в версии развития Django.

Django чтит все элементы в список/кортеж; до 1,4 года соблюдался только первый.

Смежные вопросы