django-advanced-filters icon indicating copy to clipboard operation
django-advanced-filters copied to clipboard

SimpleListFilter

Open valeriozhang opened this issue 5 years ago • 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 ! :)

valeriozhang avatar May 19 '20 15:05 valeriozhang

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

dangerousmanjay avatar Sep 10 '20 01:09 dangerousmanjay

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 avatar Sep 10 '20 05:09 asfaltboy

@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

dangerousmanjay avatar Sep 10 '20 08:09 dangerousmanjay