【问题标题】:Custom Regroup Order自定义重组顺序
【发布时间】:2011-08-12 22:25:55
【问题描述】:

我想使用自定义排序方案重新排序 Django 模板中的查询集。

这是模板代码:

{% regroup teams_at_school by season.school_year as teams %}
    <ul id="sport-picker">
        <li class="first"><span>Sports by year</span></li>
            {% for team_grouper in teams|dictsort:"season__school_year" %}
            <li><span>{{ team_grouper.grouper }}<img src="http://hometeam.s3.amazonaws.com/graphics/down-pointer.png"></span>
                <ul class="dropper">
                    {% for team_list in team_grouper.list|dictsort:"sport.sport" %}
                    <li><a href="{{ team_list.season.season_start_date.year }}/{{ team_list.sport.sport_slug }}/">{{ team_list.sport }} {% if team_list.total_wins > 0 or team_list.total_losses > 0 %}({{ team_list.total_wins }}-{{ team_list.total_losses }}){% endif %}</a></li>
                    {% endfor %}
                </ul>
            </li>
            {% endfor %}
    </ul>

产生这个输出:


如您所见,学年的排序并不理想。数据在数据库中以这种方式出现:

 id | school_year 
----+-------------
  1 | 2010-2011
  2 | 2009-2010
  3 | 2011-2012

我想按年份重新排序结果。在 SQL 中,这会这样表达:

select * from seasons_schoolyear order by substring(school_year from 1 for 4);

结果如下:

 id | school_year 
----+-------------
  2 | 2009-2010
  1 | 2010-2011
  3 | 2011-2012

有没有办法在创建查询集的语句中实现这种排序:

teams_at_school = Team.objects.filter(school=team).order_by('season__school_year')

或在模板的regroup 语句中?

【问题讨论】:

    标签: django django-templates django-views


    【解决方案1】:

    像这样将 dictsort 添加到您的重组标签中:{% regroup teams_at_school|dictsort:"school_year" by season.school_year as teams %} 并在 for 标签下方删除 teams 的 dict 排序。

    【讨论】:

    • 感谢您的建议。我这样实现了你的建议(因为school_year 是外键相关对象Season 的属性,而不是Team 的属性):{% regroup teams_at_school|dictsort:"season.school_year" by season.school_year as teams %}。这似乎并没有重新排列团队,但奇怪的是,它导致了两个学年的重复。而不是上面列出的三个学年,我现在有五个(两个重复)。
    【解决方案2】:

    您可以使用额外的查询集来创建您需要订购的值,例如:

    Team.objects.filter(school=team).select_related(depth=1)
        extra(select={"first_year":"SUBSTRING(yourmodule_school.year from 1 for 4)"}).
        order_by("-first_year")
    

    yourmodule_school 应该是数据库中的一个表,它必须在 Team 上有一个外键。

    您可以使用导入 django.db.connection 并执行 connection.queries 来检查查询是否符合您的预期,这要归功于 select_related(depth=1)。如果模块上有多个外键,则另一种无需进行不必要连接的方法是对额外字段执行 SELECT 查询,如下所示:

    Team.objects.filter(school=team).
        extra(select={"first_year":"SELECT SUBSTRING(year from 1 for 4)
        FROM yourmodule_school WHERE id=school_id"}).
        order_by("-first_year")
    

    其中 school_id 应该是您团队班级中名为 school 的外键。

    这样,查询为可用于排序的选择创建了一个新值。 here 是 extra() 的文档以防万一。

    【讨论】:

    • 感谢您的建议。但是,school_year 是 Season 模型中的一个字段,它作为外键与 Team 模型关联。有没有办法将.extra() 与外键一起使用?
    【解决方案3】:

    由于没有可行的服务器端解决方案,我求助于客户端解决方案,通过 jQuery 重新排序列表:

    $( "#sport-picker > li.first" ).after( $( "#sport-picker" ).find( "li > span:contains('2011-2012')" ).parent() );
    

    【讨论】:

      猜你喜欢
      • 2019-08-20
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 2014-12-20
      • 1970-01-01
      相关资源
      最近更新 更多