【问题标题】:Filtering by custom date range in Django admin在 Django admin 中按自定义日期范围过滤
【发布时间】:2010-12-12 16:45:30
【问题描述】:

Django 管理站点能否按自定义日期范围选择条目,即使用两个DateFields 和AdminDateWidget?我知道有date_hierarchy 和list_filter 属性,但是当有很多数据库条目并且您只需要通过精确的date__gte 和date__lte 查询过滤项目时,它们似乎不是很有用。

【问题讨论】:

    标签: django date filter django-admin


    【解决方案1】:

    注意:我在 2009 年写了这个答案,当时所需的功能在 Django 中作为公共 API 不可用。对于 Django 1.4+,请参阅其他答案。

    据我所知,此功能尚未提供,但您可以自己构建。

    首先,您可以在 url 中使用 date__gte 和 date__lte 作为 GET 参数过滤项目。

    例如

    /admin/myapp/bar/?date__gte=2009-5-1&date__lt=2009-8-1
    

    将显示日期为 2009 年 5 月、6 月或 7 月的所有条形对象。

    然后,如果您覆盖 admin/change_list.html 模板文件,您可以添加开始和结束日期的小部件,这些小部件导航到所需的 url。


    向Daniel's answer 致敬另一个 SO 问题,它教会了我如何使用查询集过滤器参数作为 GET 参数。

    【讨论】:

    • 非常感谢,非常有用的功能。
    【解决方案2】:

    https://github.com/runekaagaard/django-admin-filtrate 中的 DateRangeFilter() 类就是这样做的 :)

    【讨论】:

    • 未在 1.4 上测试,所以可能不会。我认为 1.4 中有一个新的管理过滤器 API 会改变现状。
    【解决方案3】:

    我最终以这样的方式实现它,admin.py:

     class FooAdmin(MyModelAdmin):
    
         def changelist_view(self, request, extra_context=None):
    
             extra_context = extra_context or {}
             try:
                 extra_context['trade_date_gte'] = request.GET['date__gte']
             except:
                 pass
    
             try:
                 extra_context['trade_date_lte'] = request.GET['date__lte']
             except:
                 pass
    
         return super(FileNoteAdmin, self).changelist_view(request, extra_context)  
    

    change_list.html:

    {% extends "admin/admin/change_list.html" %}
    {% load i18n admin_static admin_list %}
    {% load url from future %}
    {% load admin_urls %}
    
    
    {% block filters %}
    
    {% if cl.has_filters %}
      <div id="changelist-filter">
        <h2>{% trans 'Filter' %} </h2>
    
    <h3>By trade date</h3>
    
    <link href="/media/css/ui-lightness/jquery-ui-1.8.19.custom.css" rel="stylesheet" type="text/css"/>
    <script src="/media/js/jquery/jquery-min.js"></script>
    <script src="/media/js/jquery/jquery-ui-1.8.19.custom.min.js"></script>
    
    <script>
    
        $(function() {
            $( "#trade_date_gte" ).datepicker({ dateFormat: 'yy-mm-dd'{% if trade_date_gte %}, defaultDate: '{{ trade_date_gte }}'{% endif %} }); 
            $( "#trade_date_lte" ).datepicker({ dateFormat: 'yy-mm-dd'{% if trade_date_lte %}, defaultDate: '{{ trade_date_lte }}'{% endif %} });
        });
    
    function applyDateFilters() {
    
        qs = location.search;
    
        if (qs.charAt(0) == '?') qs = qs.substring(1);
    
        var qsComponents = qs.split(/[&;]/g);
    
        new_qs = [];
        for (var index = 0; index < qsComponents.length; index ++){
    
            var keyValuePair = qsComponents[index].split('=');
            var key          = keyValuePair[0];
            var value        = keyValuePair[1];
    
            if(key == 'trade_date__gte' || key == 'trade_date__lte' || key == '') {
                continue;
            } else {
                new_qs[index] = key + '=' + value;
            }
        }
    
        if($( "#trade_date_gte" ).val() != '') {
            new_qs[new_qs.length] = 'trade_date__gte=' + $( "#trade_date_gte" ).val();
        }
        if($( "#trade_date_lte" ).val() != '') {
            new_qs[new_qs.length] = 'trade_date__lte=' + $( "#trade_date_lte" ).val();
        }
    
        window.location = '?' + new_qs.join("&");
    }
    </script>
    
    <p>
    From: <br /><input type="text" id="trade_date_gte" value="{{ trade_date_gte|default:'' }}" size="10"><br />
    To: <br /><input type="text" id="trade_date_lte" value="{{ trade_date_lte|default:'' }}" size="10">
    </p>
    
    <ul>
        <li><a href="#" onclick="javascript:applyDateFilters();">Apply date filters</a></li>
    </ul>
    
        {% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
      </div>
    {% endif %}
    {% endblock %}
    

    被过滤的日期列是trade_date。

    【讨论】:

    • 现在我最终也使用了您的过滤器(稍微定制) - 在 django-admin-filtrate 方面仍然没有任何内容。仍然缺乏 1.4 支持
    【解决方案4】:

    在 django 1.4 中,您可以使用list_filter。试试:

    from django.contrib.admin import DateFieldListFilter
    class PersonAdmin(ModelAdmin):
        list_filter = (
            ('date_field_name', DateFieldListFilter),
        )
    

    这将提供一些内置范围,但如果您将日期范围放在 url 中,它将起作用,例如:

    ?date__gte=2009-5-1&date__lt=2009-8-1
    

    如果您需要一个日期选择器(如 jquery),那么您需要扩展 DateFieldListFilter。我向 django-admin-filtrate 发送了一个补丁,所以,请尽快检查。

    【讨论】:

    • 也可用作“自日期以来的行数”,如 ?date__gte=2009-5-1
    • 如何过滤最新的,因为现在我把最旧的放在最前面。 解决方案我不得不像这样添加一个减号-date。
    【解决方案5】:

    现在可以使用标准 Django API 轻松实现自定义管理过滤器。 list_filter 中的文档日,您现在可以添加:

    继承自 django.contrib.admin.SimpleListFilter 的类,您需要为其提供 title 和 parameter_name 属性并覆盖查找和查询集方法

    然后他们继续前进到demo(滚动到第二个项目符号)。我自己使用它来添加过滤器,其与对象的底层关系不是通过模型属性,而是通过它们上的方法的结果,这是传统过滤器不提供的。

    【讨论】:

    • 确实,很有帮助,tx
    【解决方案6】:

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-14
    • 2013-05-24
    • 2020-03-09
    • 2014-09-04
    • 1970-01-01
    • 2020-03-05
    • 2017-08-05
    • 2011-09-03
    相关资源
    最近更新 更多