2009-11-03 13 views
14

Can Django admin site seleziona le voci in base a un intervallo di date personalizzato, ovvero utilizzando due DateFields con AdminDateWidget? So che ci sono le proprietà date_hierarchy e list_filter, ma non sembrano molto utili quando ci sono molte voci di DB e basta filtrare gli articoli con la query esatta date__gte e date__lte.Filtro per intervallo di date personalizzato in admin Django

risposta

20

Nota: ho scritto questa risposta nel 2009, quando la funzionalità richiesta non era disponibile in Django come API pubblica. Per Django 1.4+, vedi le altre risposte.

Questa funzionalità non è fornita per quanto ne so, ma è possibile crearla da soli.

In primo luogo, è possibile filtrare gli elementi utilizzando date__gte e date__lte come ottenere gli argomenti nell'URL.

Per esempio

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

visualizzerà tutti gli oggetti a barre con date a maggio, giugno o luglio 2009.

Poi, se si sovrascrive il file admin/change_list.html modello, è possibile aggiungere widget per le date di inizio e fine , che naviga nell'URL richiesto.


Punta di cappello a Daniel's answer ad un altro SO questione, che mi ha insegnato sull'utilizzo di parametri di filtro QuerySet come ottenere gli argomenti.

+0

Grazie mille, caratteristica molto utile. –

5

La classe DateRangeFilter() trovato alla https://github.com/runekaagaard/django-admin-filtrate fa proprio questo :)

+0

non sembra funzionare per Django 1.4 –

+0

Non testato su 1.4 quindi probabilmente non. Penso che ci sia una nuova API del filtro di amministrazione in 1.4 che potrebbe scuotere le cose. –

3

ho finito attuazione qualcosa di simile:

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

La colonna data di essere filtrato è "trade_date".

+0

ora ho finito per usare il filtro (un po 'su misura), come pure - non c'è ancora nulla là fuori in termini di django-admin-filtrato. Manca ancora il supporto 1.4 – kosta5

32

In django 1.4, è possibile l'utente list_filter. Prova:

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

Questo darà alcuni intervalli built-in, ma funzionerà se si mette l'intervallo di date in url, come:

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

Se avete bisogno di un selettore di data (come jQuery) , che è necessario estendere DateFieldListFilter. Ho inviato una patch a django-admin-filtrate, quindi, controlla lì presto.

+1

funzionerà con admin django grappeli? – andi

+0

@andi dovrebbe funzionare. – maciek

5

Ora è possibile implementare facilmente i filtri di amministrazione personalizzati utilizzando le API standard di Django. Il giorno docs che nel list_filter, è ora possibile aggiungere:

una classe che eredita da django.contrib.admin.SimpleListFilter, che è necessario fornire il titolo e parameter_name attributi per e sovrascrivere le ricerche e metodi set di query

E vanno avanti a demo (scorrere fino al secondo punto). L'ho usato io stesso per aggiungere filtri la cui relazione di base agli oggetti non è tramite gli attributi del modello, ma i risultati dei metodi su di essi, qualcosa che i filtri tradizionali non offrono.

+1

perché il down-vote? – nemesisfixx

+0

anzi, molto utile, tx – ptim

Problemi correlati