【问题标题】:Ordering dictionary in context Django在上下文 Django 中排序字典
【发布时间】:2017-05-25 23:41:41
【问题描述】:

我看了这个thread,有一个排序字典的例子。

我有一个程序对象字典,其中键是程序对象,值是相关项目对象数量的查找。

def DepartmentDetail(request, pk):
    department = Department.objects.get(pk=pk)
    programmes = Programme.objects.all().filter(department=department).exclude(active=False).order_by('long_name')
    combi = {}
    for p in programmes:
        prj = Project.objects.all().filter(programme=p)
        combi[p] = str(len(prj))
    return render(request, 'sysadmin/department.html',{'department': department, 'programmes': programmes, 'combi': sorted(combi.items())})

在模型中,程序返回一个字符串'long_name',所以我相信我正在尝试对一个字符串键和一个字符串值进行排序。

在模板中,我得到了键和值,

{% for programme, n in combi %}

这给了我错误..

unorderable types: Programme() < Programme()

我不太明白这个错误,在 python 3 documentation 中它声明 sorted() 方法接受任何可迭代的 - 那么为什么会发生这种情况?

我正在查看 collections.OrderedDict 来解决问题,但我想知道为什么这不起作用。

谢谢。

【问题讨论】:

    标签: django python-3.x dictionary


    【解决方案1】:

    在列上有索引的数据库非常擅长排序。几乎不需要在客户端进行排序。您几乎总是可以在服务器中执行此操作。有趣的是,您显然也知道该怎么做。

     ....exclude(active=False).order_by('long_name')  # <--- this
    

    猜猜看,您的数据已经排序,不需要在 python 中再次排序!!

    但是您的代码中有一个更大的问题。您正在获取一组Project 项目,然后循环通过该集合以重新逐个检索它们。因此,如果您有 200 个 Project 项目,那么您正在执行 200 个查询,而一个查询也可以完成这项工作。只需添加select_relatedprefetch_related,具体取决于您的关系方向。

    理想情况下,您的代码应该是这样的

    department = Department.objects.get(pk=pk)
        programmes = Programme.objects.all().filter(department=department).exclude(active=False).order_by('long_name')
        return render(request, 'sysadmin/department.html',{'department': department, 'programmes': programmes,})
    

    据我所知,combi 只包含重复的数据。可以从programmes 访问相同的内容,例如。 programme.project_set.all() (同样,这取决于您的关系方向,您的模型未显示)

    推荐阅读:https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey

    【讨论】:

    • 我正在查找相关的 Projects 服务器端(因为这是我能想到的唯一方法),您是否建议我在客户端进行?如果是这样,正确的方法是什么?
    • 只是查看实际的组合值,似乎需要添加 annotate(project_count=Count('project'))
    • 虽然我确实阅读了 django 文档,但我被告知尽可能在视图中进行查找,而不是在模板中使用 set_all() 之类的东西。我也不确定 _set.all() 是如何工作的。似乎所有相关对象及其字段总是传递给模板 - 是这样吗?
    • 是的,在模板中执行 _set.all() 并没有什么坏处。如果您使用了 select_related (或 prefetch_related 视情况而定),所有相关对象都会自动传递给模板
    • 谢谢。我相信它与反向外键关系 prefetch_related 相关,因为项目具有程序的外键。
    【解决方案2】:

    问题是sorted 期望有一种方法能够订购物品,而默认情况下没有任何方法可以知道如何订购您的对象。您可以提供密钥

    sorted(combi.items(), key=lambda i: i.long_name)
    

    【讨论】:

    • 虽然这可能会修复“不可排序的类型”错误,但您应该使用e4c5's solution
    猜你喜欢
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2012-03-03
    • 2016-05-23
    • 1970-01-01
    • 2019-05-08
    • 2016-05-26
    相关资源
    最近更新 更多