【问题标题】:Iterate through an object in Django template遍历 Django 模板中的对象
【发布时间】:2016-11-12 07:10:36
【问题描述】:

在 Django 1.9 中,我有一个包含汽车品牌的数据库表。我正在尝试建立汽车品牌的索引(就像教科书后面的索引)。例如:

A
阿斯顿马丁
奥迪
...
B
宾利
宝马
...

这是我的 view.py 中的代码:

def home(request):

    car_index = {}
    alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N',
        'O','P','Q','R','S','T','U','V','W','X','Y','Z']

    for letter in alphabet:
        car_index[letter] = {}
        car_index[letter]['title'] = letter
        car_index[letter]['brands'] = Cars.objects.filter(brand__startswith = letter)

    return render(request, 'cars/home.html', {'car_index':car_index})

这是来自我的 home.html 模板的代码:

{% for each in car_index %}

    {{ each.title }}

    {% for brand in each.brands %}
        <a href="{{ brand.link }}">{{ brand.name }}</a><br>
    {% endfor %}

{% endfor %}

在 view.py 中,我在查询集中尝试了.values(),在模板上下文中尝试了.items()。在模板中,我试过car_index.itemseach.brands.itemseach.brands[0]。没有任何效果。使用上面的代码,我得到标题:E D X I A U H B T S N K Q Z J Y W V O L R F G P C M,但没有链接。 (我知道如何排序,但首先处理链接)

我已阅读:

https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#for

how to iterate through dictionary in a dictionary in django template?

【问题讨论】:

  • 看起来不错,如果您在模板中打印each.brands,您会看到什么?
  • 你能显示{% for each in car_index %} {{each}} {% endfor %}的结果吗?你也试过{% for key, value in each.items %}
  • @doniyor each.brands 是空白的。 @KapilSachdev,您的评论帮助我弄清楚了。将代码修改为:{% for k,v in car_index.items %}{{ v.title }}{% for brand in v.brands %}。啊,在回到其他 SO 答案之后,我现在可以一目了然地看到答案。但是由于他们的数据结构有点不同,我的大脑并没有实现飞跃。多谢你们。我不知道将接受的答案授予回答的评论的 SO 礼仪。

标签: django


【解决方案1】:

更好的方法 - 更简洁的代码,除了数据库效率:

alphabet = ['A','B','C','D','E','F','G', ..]

brands_list = []
for letter in alphabet:
    letter_ = {'cars': Cars.objects.filter(brand__startswith=letter), 'letter': letter}
    brands_list.append(letter_)

return render(request, 'cars/home.html', {'brands': brands_list})

模板

{% for brand in brands %}    
    {{ brand.letter }}    
    {% for car in brand.cars %}
        <a href="{{ car.link }}">{{ car.name }}</a><br>
    {% endfor %}
{% endfor %}

【讨论】:

  • 哇,乍一看和我的代码很相似,但实际上却大不相同。学到了很多,谢谢!我将其标记为已接受的答案有几个原因:首先,brands_list 的结构比我的 car_index 更好,因为它消除了我添加的密钥 (car_index[letter]),从而消除了对 {% for k,v in car_index.items %} 的需要。更好看的模板,这就是我认为模板最初应该如何工作的方式。其次,它使用数组而不是我使用的对象,这意味着我不再需要对对象进行排序 - 字母按顺序排列。
  • @FeFiFoFu 很高兴我能帮上忙
【解决方案2】:

我可以劝阻你放弃目前的做法吗?

您正在执行 26 步的全表扫描。如果品牌列不是唯一的,您会发现名称会重复。如果您有数百万条记录,您将耗尽内存。如果brand列没有索引,你会发现下面的查询非常非常慢:

Cars.objects.filter(brand__startswith = letter)

有一个非常简单的解决方案。这也可能涉及全表扫描,但至少您正在执行一个慢速查询而不是 26 个。

Cars.objects.raw('SELECT max(id), SubStr(brand,1,1) AS letter, brand
    FROM myapp_cars GROUP BY substr(brand,1,1)')

这是使用原始查询。如果您不喜欢它们并且有幸使用 Postgresql,您可以使用distinct 客观地更优雅地实现相同目标。

【讨论】:

  • 我明白你在说什么。我不精通 SQL,所以我只是在不理解的情况下复制您的代码,这很糟糕。但是感谢您指出效率低下。一旦完成第 1 版,我将学习 SQL 和/或更改 python 代码以访问 DB 一次。
  • 您好,当我遇到这个问题时,我正在查看我的一些旧答案。这是怎么回事?
  • 我很高兴听到 :)
【解决方案3】:

很高兴我的评论以某种方式帮助您解决了问题。 我只是将其发布为答案,以便对其他人有所帮助。

{% for each in car_index %},只是迭代出当前的dict,而不是dictsdict,即品牌字典

由于 car_index 上下文包含一个字典,以下内容将显示 car_index 字典的键和值并解压缩品牌字典。

{% for key,value in car_index.items %}

    {{ value.title }}

    {% for brand in value.brands %}
        <a href="{{ brand.link }}">{{ brand.name }}</a><br>
    {% endfor %}

{% endfor %}

【讨论】:

    猜你喜欢
    • 2012-12-25
    • 2011-11-10
    • 1970-01-01
    • 2018-05-24
    • 2019-11-24
    • 2018-04-23
    • 2014-07-15
    • 2023-01-10
    • 2017-08-13
    相关资源
    最近更新 更多