silentsokolov / django-admin-rangefilter

A Django app that lets you filter data by date range and numeric range in the admin UI
MIT License
713 stars 106 forks source link

Specifying default values #44

Closed wolph closed 4 years ago

wolph commented 4 years ago

It would be really useful to specify a default date/time range. For example, today, last 7 days, this week, etc.

My use case is that I have a lot of data and a few heavy queries which make querying without a date limit prohibitively slow. As a workaround I'm currently doing something like this, but it's clunky at best:

class SomeAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        if not request.GET.get('created_at__range__gte_0'):
            today = datetime.now()
            yesterday = today - timedelta(days=1)

            # make sure request.GET is mutable
            request.GET = request.GET.copy()
            request.GET['created_at__range__gte_0'] = str(yesterday.date())
            request.GET['created_at__range__gte_1'] = '0:00:00'

        return super().get_queryset(request)
silentsokolov commented 4 years ago

Now (on the master branch) you can use a specific method get_rangefilter_{field}_default in the ModelAdmin, it set initial values for range fields. For example:

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_filter = (
        ('created_at', DateRangeFilter), ('updated_at', DateTimeRangeFilter),
    )

    def get_rangefilter_created_at_default(self, request):
        return (datetime.date.today, datetime.date.today)

Вut the filter will not be applied! Use get_queryset for initial query. For example:

def get_queryset(self, request):
    queryset = super().get_queryset(request)

    if not 'created_at__range' in request.path:
        default_gte, default_lte = self.get_rangefilter_created_at_default(request)
        queryset.filter(...)

    return queryset

If you want to use "preset", please read a issue #1 and list_filter

wolph commented 4 years ago

Awesome! Thank you for the quick fix. I'll start testing it :)

wolph commented 4 years ago

Works perfect, thank you :)

brocasm commented 2 years ago

When i use get_queryset to apply initial query, doesn't work:

def get_queryset(self, request): queryset = super().get_queryset(request)

if not 'created_at__range' in request.path:
    default_gte, default_lte = self.get_rangefilter_created_at_default(request)
    queryset.filter(created_at_gte=default_gte)

return queryset

What i do wrong ? With many tries, i think my queryset.filter is wrong... I try without if statement with same result.

Thanks for help

silentsokolov commented 2 years ago
queryset = queryset.filter(...)

return queryset
brocasm commented 2 years ago
queryset = queryset.filter(...)

return queryset

Thx a lot