Django admin:list_display 中的二级排序

发布于 2024-10-09 20:32:20 字数 225 浏览 2 评论 0原文

在 Django 管理员的 list_display 中显示模型时,我想首先按一列排序,然后按另一列排序。
这是一个示例模型:

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

如何实现这一点?

While showing a model in Django's admin's list_display, I'd like to sort first by one column, then by another.
Here's an example model:

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

How could this be achieved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故人的歌 2024-10-16 20:32:20

我认为您正在寻找管理类的“排序”属性。

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

编辑:我之前的答案是不正确的。根据上面的文档,Django 仅尊重元组中的第一个条目。有/曾经有一张票来解决这个问题,但没有任何结果。我还尝试了各种其他建议的解决方案,但它们似乎都不适合我的 Django 版本。

然而,今天我作为项目的一部分回到了这个问题,并终于找到了对我有用的东西。我的解决方案基于此 Django 代码片段,为了完整起见,我将在此处发布代码片段。

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)

I think you are looking for the "ordering" attribute of an admin class.

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

Edit: My previous answer is incorrect. According to the documentation above, Django only honors the first entry in the tuple. There is/was a ticket to resolve this that went nowhere. There are various other proposed solutions that I also tried, but none of them seemed to work with my version of Django.

However, I came back to this problem today as part of a project and finally found something that worked for me. My solution was based upon this Django snippet, and I will post the snippet code here for completeness.

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)
脸赞 2024-10-16 20:32:20

这是基于 bogeyman 4 月 1 日编辑的答案,但细分为基本功能。

在我的 models.py 中,像往常一样在模型 Meta 中定义 ordering

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 最终成为按模型元中指定的顺序排序。

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) 并添加定义 的列表CustomerAdmin 中的 >ordering = ['the_date', 'name']

This is based on bogeyman Apr 1 edited answer, but broken down to the essential feature.

In my models.py define ordering in the models Meta as usual:

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.

Then in admin.py subclass ChangeList, but force the query_set to ultimately be sorted by the ordering specified in the Meta of the model.

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)

If you'd rather define the ordering in the ModelAdmin; you could do that as well; just change return queryset.order_by(*self.model._meta.ordering) to return queryset.order_by(*self.model_admin.ordering) and add a list defining ordering = ['the_date', 'name'] in CustomerAdmin.

拔了角的鹿 2024-10-16 20:32:20

您可以通过使用 Django trunk 而不是 1.3

https://docs.djangoproject 来实现此目的.com/en/dev/ref/contrib/admin/

Django 开发版本中的新增功能。

如果需要指定动态
为了(例如根据用户或语言)你可以实现
get_ordering() 方法。

在 Django 开发版本中进行了更改。

Django 尊重以下所有元素
列表/元组;在 1.4 之前,只尊重第一个。

You can achieve this by using Django trunk rather than 1.3

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

New in Django Development version.

If you need to specify a dynamic
order (for example depending on user or language) you can implement a
get_ordering() method.

Changed in Django Development version.

Django honors all elements in
the list/tuple; before 1.4, only the first was respected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文