2009-11-03 20 views
14

Kann Django Admin-Site Einträge nach einem benutzerdefinierten Zeitraum auswählen, d. H. Mit zwei DateFields mit AdminDateWidget? Ich weiß, dass es date_hierarchy und list_filter Eigenschaften gibt, aber sie scheinen nicht sehr nützlich, wenn es viele DB-Einträge gibt und Sie nur Elemente durch genaue date__gte und date__lte Abfrage filtern müssen.Filtern nach benutzerdefinierten Datumsbereich in Django admin

Antwort

20

Hinweis: Ich schrieb diese Antwort im Jahr 2009, als die erforderliche Funktionalität in Django als öffentliche API nicht verfügbar war. Für Django 1.4+, siehe die anderen Antworten.

Diese Funktion wird, soweit mir bekannt ist, nicht zur Verfügung gestellt, Sie können sie jedoch selbst erstellen.

Erstens können Sie Elemente filtern, indem Sie date__gte und date__lte als GET-Argumente in der URL verwenden.

Zum Beispiel

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

werden alle Objekte der mit Terminen im Mai, Juni oder Juli 2009. Dann

angezeigt, wenn die admin/change_list.html Vorlagendatei überschreiben, können Sie Widgets für Start- und Enddatum hinzufügen , die zur gewünschten URL navigieren.


Hutspitze zu Daniel's answer zu einem anderen SO Frage, die mich gelehrt, über queryset Filterparameter verwendet als Argumente GET.

+0

Vielen Dank, sehr nützliche Funktion. –

5

Die DateRangeFilter() Klasse bei https://github.com/runekaagaard/django-admin-filtrate gefunden macht genau das :)

+0

Scheint nicht für Django 1.4 –

+0

Nicht auf 1,4 so wahrscheinlich nicht getestet. Ich denke, es gibt eine neue Admin-Filter API in 1.4, die Dinge aufrütteln würde. –

3

ich es so etwas wie dies am Ende der Umsetzung:

# 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 %} 

Die Spalte Datum gefiltert wird, ist „trade_date“.

+0

Jetzt habe ich auch Ihren Filter verwendet (leicht angepasst) - es gibt immer noch nichts in Bezug auf Django-Admin-Filtrat. Noch fehlt 1.4 Unterstützung – kosta5

32

In Django 1.4 können Sie Benutzer list_filter. versuchen:

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

Dies wird einige eingebaute in Bereichen geben, aber es wird funktionieren, wenn Sie den Datumsbereich in url setzen, wie:

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

Wenn Sie eine Datumsauswahl (wie jquery) benötigen , als Sie erweitern müssen DateFieldListFilter. Ich habe einen Patch an django-admin-filtrate geschickt, also, checkt dort bald.

+1

wird es mit Django Grappeli Admin arbeiten? – andi

+0

@andi sollte es funktionieren. – maciek

5

Es ist jetzt möglich, einfach benutzerdefinierte Admin-Filter mit Standard-Django-APIs zu implementieren. Der docs Tag, dass in den list_filter, können Sie jetzt hinzufügen:

eine Klasse von django.contrib.admin.SimpleListFilter vererben, die Sie den Titel zur Verfügung stellen müssen und parameter_name Attribute der Lookups und queryset Methoden und außer Kraft setzen

Und sie gehen weiter zu demo (scrollen Sie zu der zweiten Kugel). Ich habe das selbst benutzt, um Filter hinzuzufügen, deren zugrundeliegende Beziehung zu den Objekten nicht über Modellattribute, sondern über Methodenresultate besteht, die die traditionellen Filter nicht bieten.

+1

warum die down-stimme? – nemesisfixx

+0

in der Tat, sehr hilfreich, TX – ptim

Verwandte Themen