【问题标题】:Django Admin: Order by value on related Foreign KeyDjango Admin:按相关外键的值排序
【发布时间】:2012-04-19 19:05:03
【问题描述】:

我正在尝试按对象相关外键集中的特定值对 Django 管理列表页面进行排序。

具体来说,在下面的代码中,我希望 ContentAdmin 视图显示按“Twitter Score”排序的所有内容对象的列表(名为“Twitter”的 Score 对象)。

在 django 应用中,我有以下模型:

class Content(models.Model):
    body = models.CharField(max_length=564)
    title = models.CharField(max_length=64) 

class Score(models.Model):
    name = models.CharField(max_length=64)
    score = models.IntegerField()
    content = models.ForeignKey('Content')

在 admin.py 我有以下内容:

class ContentAdmin(admin.ModelAdmin):
    list_display = ('title', 'show_twitter_score',)

    def show_twitter_score(self, obj):
        twitter_score = obj.score_set.get(name='Twitter')
        return 'Twitter: ' + str(twitter_score.score)

目标:ContentAdmin 的管理面板显示按“Twitter”分数排序的内容对象

谢谢大家!

【问题讨论】:

  • 管理面板是指admin.py?你有admin.site.register(Content, ContentAdmin)吗?
  • 我的代码不做排序,它只显示分数
  • 是的,通过管理面板,我的意思是 admin.py。刚刚解决了这个问题另外,我已经正确注册了所有模型。
  • 听起来很糟糕,但是您是否尝试单击列标题进行排序?
  • @TommasoBarbugli,我希望是我这么笨!不幸的是,单击列标题不适用于定义为函数的列

标签: python django django-admin


【解决方案1】:

我通过扩展ContentAdmin 类的get_queryset 方法解决了这个问题。之后,只需获取正确的 ORM 查询即可

def get_queryset(self, request):
    qs = super(ContentAdmin, self).get_queryset(request)
    return qs.filter(score__name='Twitter').order_by('-score__score')

对于 Django 1.5 及更早版本,方法为 queryset。

def queryset(self, request):
    qs = super(ContentAdmin, self).queryset(request)
    return qs.filter(score__name='Twitter').order_by('-score__score')

【讨论】:

    【解决方案2】:

    如果我理解正确,您可以从 Django 文档中的ModelAdmin.list_display 尝试:

    通常,不是实际数据库字段的list_display 元素不能用于排序(因为 Django 在数据库级别进行所有排序)。

    但是,如果list_display 的元素代表某个数据库字段,则可以通过设置项目的admin_order_field 属性来表明这一事实。

    例如:

    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        color_code = models.CharField(max_length=6)
    
        def colored_first_name(self):
            return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
        colored_first_name.allow_tags = True
        colored_first_name.admin_order_field = 'first_name'
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'colored_first_name')
    

    上面将告诉 Django 在管理员中尝试按 colour_first_name 排序时按 first_name 字段排序。

    您可以在代码中尝试使用此解决方法进行排序。

    【讨论】:

    • 感谢 Cesar,但我认为这对我不起作用。使用 list_display 我无法指定 content_obj.score_set 中我想要排序的多个分数中的哪一个。另外,我可以为你澄清我的问题吗?我想确保每个人都能理解它
    • 当然,只需重新编辑您的帖子并更改您需要的内容。对不起,也许我误解了整个事情,这不是我第一次:(
    • 在底部为 GOAL 做了一个小编辑,但不幸的是,我不知道如何表达这个问题。感谢您尝试 Cesar!
    【解决方案3】:

    由于 django admin 使用 db 进行排序,因此您无法对列表中显示的功能进行排序。

    您可以做的是将要显示的列添加到 django 管理员用来列出您的模型的查询集中,这样您就可以进行排序。

    要添加您需要的列,您必须使用 queryset extra 方法。

    这应该可以解决问题:)

    Content.objects.all().extra(select={'twitter_score': 'SELECT score from content_score WHERE content_score.id = content_content.id'})
    

    奖金回合:

    Content.objects.all().extra(select={'twitter_score': 'SELECT 'Twitter score:' || score from content_score WHERE content_score.id = content_content.id'})

    【讨论】:

    • 在 ORM 领域内绝对可以做到这一点。我找到了一个解决方案,我很快就会发布,当我有的时候我会在这里评论:)
    • 其实我还要等一段时间才能回答,再过8个小时我不准!
    • @djs22 我很想看到这个 :)
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2019-01-21
    • 2011-09-12
    • 2017-04-06
    • 2014-03-16
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多