Test a custom filter in admin.py
Asked Answered
E

2

6

I've the following filter in my admin.py file:

class parentCategoryFilter(admin.SimpleListFilter):
    title = 'parent category'
    parameter_name = 'parent_category'

    def lookups(self, request, model_admin):
        first_level_categories = model_admin.get_queryset(request).filter(parent_category__isnull=True)

        if first_level_categories:

            lookups = (('none', 'None'),)

            for first_level_category in first_level_categories:
                lookups += ((first_level_category.id, first_level_category.name),)

            return lookups

    def queryset(self, request, queryset):
        if self.value() == 'none':
            return queryset.filter(parent_category__isnull=True)
        elif self.value():
            try:
                return queryset.filter(parent_category=int(self.value()))
            except (ValueError, TypeError):
                return queryset.none()
        else:
            pass

And I want to test it in my tests.py file, however while trying to instantiate the class it starts asking me about 5 __init__ parameters. Is it possible to test this filter functionality?

Eclair answered 25/5, 2013 at 15:57 Comment(0)
I
6

The 5 parameters that __init__ needs is from admin.SimpleListFilter whose __init__ is defined as: (Source)

def __init__(self, request, params, model, model_admin):

You can pass in those parameters to test your filter

Inflationism answered 25/5, 2013 at 19:12 Comment(1)
Thanks, I'll post the solution so other can see it.Eclair
E
15

Thanks to karthikr and lots of reading I've came up with the following solution (using Django's Pool example):

The filter method is defined as follows:

class WasPublishedRecentlyFilter(admin.SimpleListFilter):
    title = 'Was published recently'
    parameter_name = 'published_recently'

    def lookups(self, request, model_admin):
        return (
            ('yes', 'Yes',),
            ('no', 'No',),
        )

    def queryset(self, request, queryset):
        if self.value() == 'yes':
            #filter logic
        elif self.value() == 'no':
            #filter logic
        elif self.value():
            return queryset.none() 

And the test for the filter:

def test_filter(self):
    Poll.objects.create(question='Sup?', pub_date=timezone.now())
    Poll.objects.create(question='How you doing?', pub_date=timezone.now() - datetime.timedelta(days=1))

    filter = admin.WasPublishedRecentlyFilter(None, {'published_recently':'yes'}, Poll, admin.PollAdmin)
    poll = filter.queryset(None, Poll.objects.all())[0]
    self.assertEqual(poll.question, 'Sup?')

    filter = admin.WasPublishedRecentlyFilter(None, {'published_recently':'no'}, Poll, admin.PollAdmin)
    poll = filter.queryset(None, Poll.objects.all())[0]
    self.assertEqual(poll.question, 'How you doing?')

And the output:

Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.124s

OK
Destroying test database for alias 'default'...
Eclair answered 27/5, 2013 at 15:48 Comment(1)
This answer seems to be a bit outdated, but If you are checking this and you are using Django 2.0, here's how Django tests SimpleListFilterFrieze
I
6

The 5 parameters that __init__ needs is from admin.SimpleListFilter whose __init__ is defined as: (Source)

def __init__(self, request, params, model, model_admin):

You can pass in those parameters to test your filter

Inflationism answered 25/5, 2013 at 19:12 Comment(1)
Thanks, I'll post the solution so other can see it.Eclair

© 2022 - 2024 — McMap. All rights reserved.