Динамически писать django фильтры - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть Django фильтры для пары моделей. но они оба имеют одинаковую фильтрацию, как сделать это DRY.

class TestFilter(django_filters.FilterSet):
    field_list = Test._meta.get_fields()
    for field in field_list:
        field_name = (field.__str__().split('.'))[-1]

    if type(field) is model.CharField:
        field_name__contains = field_name + '__contains'
        vars()[field_name] = django_filters.CharField(field_name=field_name, lookup_expr='iexact')
        vars()[field_name] = django_filters.CharField(field_name=field_name, lookup_expr='icontains')


    class Meta:
        model = Test
        fields = '__all__'


class Test2Filter(django_filters.FilterSet):
    field_list = Test2._meta.get_fields()
    for field in field_list:
        field_name = (field.__str__().split('.'))[-1]

    if type(field) is model.CharField:
        field_name__contains = field_name + '__contains'
        vars()[field_name] = django_filters.CharField(field_name=field_name, lookup_expr='iexact')
        vars()[field_name] = django_filters.CharField(field_name=field_name, lookup_expr='icontains')


    class Meta:
        model = Test2
        fields = '__all__'

оба класса имеют одинаковый код. Я пытался переместить часть кода в утилиты, такие как функция generic_filter и импортировать функцию в файл фильтров, но фильтры не работают.

1 Ответ

0 голосов
/ 06 февраля 2020

Вы должны быть в состоянии написать фабричную функцию, которая возвращает класс. Класс может быть определен с использованием формы с тремя аргументами type. Я также не совсем понял, как использовать field_name__contains. В опубликованном коде явно есть ошибка с отступом.

Это не в моей голове и совершенно без какой-либо отладки

В прошлый раз, когда я писал что-то подобное, к тому времени, когда я начал работать, я пожалел, что беспокоился. Тем не менее, это может быть опыт обучения. Если вы проверяете эти вещи дюжиной, это может стоить вашего времени. В противном случае это может быть случай для другого вида DRY (НЕ повторяйте себя!)

def FilterFactory( model_class, class_name):

    class_vars = {}

    field_list = model_class._meta.get_fields()
    for field in field_list:

        field_name = (field.__str__().split('.'))[-1]
        if type(field) is model.CharField:
            field_name__contains = field_name + '__contains' 
            class_vars[field_name] = \
                django_filters.CharField(field_name=field_name, lookup_expr='iexact')
            class_vars[field_name+'_contains'] = \
                django_filters.CharField(field_name=field_name__contains, lookup_expr='icontains')

    class_vars['Meta'] = type( 'Meta', (object, ), {
       "model": model_class,
       "fields": "__all__"
        }
    )

    klass = type( class_name, (django_filters.FilterSet, ), class_vars )
    return klass

Использование

TestFilter = FilterFactory(  Test, 'TestFilter')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...