-1

I've created a Filter builder in my application and I would like to improve it removing unnecessary parameters Value=None of my functions popular and unanswered, working like javascript for example. The querystring parameters can be: none (all records), popular=1, unanswered=1, by=username

filters.py

class Filters:
    queryset = None

    def apply(self, queryset):
        self.queryset = queryset

        for key, value in self.request.items():
            if key in self.filters and hasattr(self, key):
                return getattr(self, key)(value)

        return self.queryset


class ThreadFilter(Filters):
    filters = ('by', 'popular', 'unanswered')
    request = None

    def __init__(self, request):
        self.request = request

    def by(self, username):
        return self.queryset.filter(username=username)

    def popular(self, value=None):
        return self.queryset.order_by('-replies_count')

    def unanswered(self, value=None):
        return self.queryset.filter(replies_count=0)

views.py

class ThreadsView(generic.ListView):
    model = Thread
    template_name = "threads/index.html"

    def get_queryset(self):
        thread_filter = ThreadFilter(self.request.GET)

        threads = thread_filter.apply(Thread.objects.all())

        channel_slug = self.kwargs.get('channel_slug', False)

        if channel_slug:
            threads = threads.filter(channel__slug=channel_slug)

        return threads

To be clear, I'm looking for an elegant way to avoid a logical test since I'm beginner in Python and it can be done in other languages like php

if value == "1": 
    return getattr(self, key) 

return getattr(self, key)(value)
Leandro Brito
  • 334
  • 2
  • 13
  • 1
    I don't think I understand the question. If you don't want your `popular` and `unanswered` methods to have a `value=None` argument, then just delete `value=None` from the function's argument list. – Kevin Feb 15 '18 at 13:38
  • I got this error popular() takes 1 positional argument but 2 were given Maybe some logic to test if the method has parameters before call getattr function – Leandro Brito Feb 15 '18 at 13:40
  • Those `value` parameters aren't unnecessary, because the code in `apply` calls those methods with an argument: `return getattr(self, key)(value)`. You can't remove them without breaking your code. – Aran-Fey Feb 15 '18 at 13:46
  • Exactly. I was looking for a elegant alternative of if value == "1": return getattr(self, key) return getattr(self, key)(value) – Leandro Brito Feb 15 '18 at 13:50
  • replace `value=None` with `*args` maybe? https://stackoverflow.com/questions/3394835/args-and-kwargs – e.s. Feb 15 '18 at 14:07

1 Answers1

0

The best solution I found was check the number of parameters

class Filters:
    queryset = None

    def apply(self, queryset):
        self.queryset = queryset

        for key, value in self.request.items():
            if key in self.filters and hasattr(self, key):
                count_param = eval('self.%s.__code__.co_argcount' % key)
                if count_param < 2:
                    return getattr(self, key)

                return getattr(self, key)(value)

        return self.queryset
Leandro Brito
  • 334
  • 2
  • 13