Adding an intermediate date range to Django Import/Export
How to add a "from" and "to" date range to the Django Import/Export export form

Django Import/Export is an excellent library for easily getting data in-and-out of your database via the Django Admin panel. You can export individual items via the Django Admin action, or you can export the entire table via an "export" button.
The user clicks the export button in the top right to export all their data
When you have a table with a lot of data in it, there's a middle ground where you want to export subset of data based on dates, but you don't want to have to manually select that data.
In this situation, it is useful to allow the user to filter the data by date range instead:
The user can then filter the entire table by a 'from' and 'to' date
In this post I'll run through how you can set this up on your own project.
Overview
Django Import/Export makes it relatively easy for us to add this functionality. It already has an intermediate admin page that presents the user with a form for exporting the data.
We need to override the default form that is used on this page, including a "from" and "to" date field. We can then use these additional fields to filter the exported data by date.
Django Model
In your model, you need to make sure you have some sort of timestamp field to filter against, for example created_on
:
class MyModel(models.Model):
# ... other fields
created_on = models.DateTimeField(auto_now_add=True)
Import/Export Resource
To export this model from the admin, you'll have a Django Import/Export resource. Here is what it will look like to begin with:
from django import forms as django_forms
from import_export import fields, resources
from import_export import forms as import_export_forms
from .models import MyModel
class MyModelResource(resources.ModelResource):
# ... other fields
created_on = fields.Field(attribute="created_on", column_name="Date")
class Meta:
model = MyModel
fields = ("created_on",)
def get_queryset(self):
# I always include the queryset here as you regularly have to
# improve the performance when exporting large tables.
return MyModel.objects.all()
Now we're going to add a few things:
- A new form to include "from date" and "to date" fields
- A mixin that can be added to your admin to include this new form by default
- Logic to filter the data when exporting according to our new dates
from django import forms as django_forms
from import_export import fields, resources
from import_export import forms as import_export_forms
from .models import MyModel
class ToFromDateFilterExportForm(import_export_forms.ExportForm):
"""A Django Import/Export export form with additional fields"""
from_date = django_forms.DateField(
label="Date from",
required=False,
widget=django_forms.DateInput(attrs={"type": "date"}),
)
to_date = django_forms.DateField(
label="Date to",
required=False,
widget=django_forms.DateInput(attrs={"type": "date"}),
)
class ToFromDateFilterAdminMixin:
"""A Django admin model mixin to include our form and logic"""
export_form_class = ToFromDateFilterExportForm
def get_export_resource_kwargs(self, request, **kwargs):
# Filter objects by to/from date
export_form = kwargs.get("export_form")
if export_form:
from_date = export_form.cleaned_data.get("from_date", None)
to_date = export_form.cleaned_data.get("to_date", None)
if from_date:
kwargs.update(from_date=from_date)
if to_date:
kwargs.update(to_date=to_date)
return kwargs
class MyModelResource(resources.ModelResource):
# ... other fields
created_on = fields.Field(attribute="created_on", column_name="Date")
class Meta:
model = MyModel
fields = ("created_on",)
def __init__(self, **kwargs):
super().__init__()
# Save the form values
self.to_date = kwargs.get("to_date", None)
self.from_date = kwargs.get("from_date", None)
def filter_export(self, queryset, **kwargs):
# Filter rows between the two dates
if self.to_date:
queryset = queryset.filter(created_on__lte=self.to_date)
if self.from_date:
queryset = queryset.filter(created_on__gte=self.from_date)
return super().filter_export(queryset, **kwargs)
def get_queryset(self):
# I always include the queryset here as you regularly have to
# improve the performance when exporting large tables.
return MyModel.objects.all()
Django Admin
Now finally, here's our admin.py
where we configure Import/Export:
from django.contrib import admin
from import_export.admin import ExportMixin
from .models import MyModel
from .resources import (
MyModelResource,
ToFromDateFilterAdminMixin,
)
@admin.register(MyModel)
class MyModelAdmin(ExportActionModelAdmin, ToFromDateFilterAdminMixin, ExportMixin):
# ... rest of admin
def get_export_resource_classes(self, request):
return (MyModelResource,)
Now your users can filter all of their data to a certain date range.