modlinltd/django-advanced-filters

SimpleListFilter

valeriozhang opened this issue · 3 comments

Is it possible to create a custom list filter for advanced_filter_fields? I have a field property in my model that I would like to search for. Thanks ! :)

same here! i am also wondering if i can use this mixin with my custom simple list filter.

This package is about exposing fields in a form for generating a db query. How do you imagine a "simple filter" of a different type will work alongside?

Can you give me an example of how this would look?

@asfaltboy
Thanks for responding so fast! 👍

here's an example

in my models.py

from django.db import models


class Brain(models.Model):
    is_sexy = models.BooleanField()


class Cell(models.Model):
    brain = models.ForeignKey(Brain, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

in my admin.py

from datetime import timedelta

from django.contrib import admin
from django.db.models import OuterRef, Subquery
from django.utils.timezone import now


class LatestCellDateTimeFilter(SimpleListFilter):
    title = 'Latest cell created at'

    parameter_name = 'latest_cell_created_at'

    def lookups(self, request, model_admin):
        return (
            ('today', 'today'),
            ('week', 'past one week'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'today':
            return queryset.filter(latest_cell_created_at=now())
        if self.value() == 'week':
            return queryset.filter(
                latest_cell_created_at=now(),
                latest_cell_created_at=now() - timedelta(weeks=1),
            )


@admin.register(Brain)
class BrainAdmin(admin.ModelAdmin):
    list_filter = (
        LatestCellDateTimeFilter,
        'is_sexy',
    )

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        cells = Cell.objects.filter(brain=OuterRef('pk')).order_by('-created_at')
        return qs.annotate(
            latest_cell_created_at=Subquery(cells.values('created_at')[:1]),
        )

In this situation, is there a way to make it work with this package other than just chaining two filters?
I know it won't work since 'latest_cell_created_at' isn't a actual field, and Django ORM doesn't support that kind of lookup. I'm hoping someone find a way to get through haha