29
Note: I wrote this answer in 2009, when the required functionality was not available in Django as a public API. For Django 1.4+, see the other answers.
This functionality isn’t provided as far as I’m aware, but you can build it yourself.
Firstly, you can filter items using date__gte
and date__lte
as GET arguments in the url.
For example
/admin/myapp/bar/?date__gte=2009-5-1&date__lt=2009-8-1
will display all bar objects with dates in May, June or July 2009.
Then if you override the admin/change_list.html template file, you can add widgets for start and end dates, which navigate to the required url.
Hat tip to Daniel’s answer to another SO question, which taught me about using queryset filter parameters as GET arguments.
54
In django 1.4, you can user list_filter. try:
from django.contrib.admin import DateFieldListFilter
class PersonAdmin(ModelAdmin):
list_filter = (
('date_field_name', DateFieldListFilter),
)
This will give some built-in ranges, but it will work if you put the date range in url, like:
?date__gte=2009-5-1&date__lt=2009-8-1
If you need a date picker (like jquery), then you need to extend DateFieldListFilter. I sent a patch to django-admin-filtrate, so, check there soon.
- [Django]-How to upgrade django?
- [Django]-How to use 'User' as foreign key in Django 1.5
- [Django]-Add an object by id in a ManyToMany relation in Django
34
You can use this up-to-date one: https://github.com/silentsokolov/django-admin-rangefilter.
- [Django]-Why am I getting this error in Django?
- [Django]-Django Count() in multiple annotations
- [Django]-How do I drop a table from SQLite3 in DJango?
12
It’s now possible to easily implement Custom Admin filters using standard Django APIs. The docs day that in the list_filter
, you can now add:
a class inheriting from django.contrib.admin.SimpleListFilter, which you need to provide the title and parameter_name attributes to and override the lookups and queryset methods
And they go ahead to demo (scroll to the second bullet). I’ve used this myself to add filters whose underlying relation to the objects isn’t via model attributes, but results of methods on them, something which the traditional filters don’t offer.
- [Django]-Using Django auth UserAdmin for a custom user model
- [Django]-How to show warnings in py.test
- [Django]-ImportError: bad magic number in 'time': b'\x03\xf3\r\n' in Django
6
I ended up implementing it something like this, 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 %}
The date column being filtered is trade_date
.
- [Django]-How to use django-debug-toolbar on AJAX calls?
- [Django]-Django admin: search for foreign key objects rather than <select>?
- [Django]-Model name of objects in django templates
5
The DateRangeFilter()
class found at https://github.com/runekaagaard/django-admin-filtrate does just that
- [Django]-Django model fields getter / setter
- [Django]-Do django db_index migrations run concurrently?
- [Django]-Add Indexes (db_index=True)