Создание динамических классов FIlter атрибутов JSONField для администратора Django

Давайте рассмотрим модель ниже в качестве примера.

from django_mysql.models import JSONField
class Student(models.Model):
    standard = models.CharField(_('Standard'), max_length=10, null=True, blank=True, choices=STANDARD_CHOICES)
    extra = JSONField()

# example data in above field might be as below
# {"name": "Bob", "buys": "tesla", "country": "India"}
# {"name": "Sam", "buys": "lamborgini", "country": "England"}
# {"name": "Izzy", "buys": "tesla", "country": "Egypt"}

Это мой базовый класс JSONFieldFilter для фильтра JSONField. Вдохновленный отсюда

class JSONFieldFilter(SimpleListFilter):

    def __init__(self, *args, **kwargs):

        super(JSONFieldFilter, self).__init__(*args, **kwargs)

        assert hasattr(self, 'title'), (
            'Class {} missing "title" attribute'.format(self.__class__.__name__)
        )
        assert hasattr(self, 'parameter_name'), (
            'Class {} missing "parameter_name" attribute'.format(self.__class__.__name__)
        )
        assert hasattr(self, 'json_field_name'), (
            'Class {} missing "json_field_name" attribute'.format(self.__class__.__name__)
        )
        assert hasattr(self, 'json_field_property_name'), (
            'Class {} missing "json_field_property_name" attribute'.format(self.__class__.__name__)
        )

    def lookups(self, request, model_admin):
        field_value_set = set()
        for data in Student.objects.values_list(
                self.json_field_name, flat=True):
            if self.json_field_property_name in data:
                field_value_set.add(data[self.json_field_property_name])
        return [(v, v) for v in field_value_set]

    def queryset(self, request, queryset):
        if self.value():
            json_field_query = {"{}__{}".format(self.json_field_name, self.json_field_property_name): self.value()}
            return queryset.filter(**json_field_query)
        else:
            return queryset

И производный класс статического фильтра, как показано ниже.

class ExtraFilter(JSONFieldFilter):
    title = _('Car bought')
    parameter_name = 'CarBought'
    json_field_name = 'extra'
    json_field_property_name = 'buys'

А затем используется выше производный класс ExtraFilter в list_filter, как показано ниже на StudentAdmin учебный класс.

class StudentAdmin(admin.ModelAdmin):
    list_filter = ('standard', ExtraFilter)

Теперь над фрагментами работает отлично. Но я хочу достичь 'To have dynamic each extra's attribute filter',

Я могу просто сохранить список где-нибудь в модели соло, где я могу ввести имена атрибутов, как...['buys', 'country'] (Идея в том, что я могу получить список активных атрибутов name и использовать его метод get_list_filter для создания класса на лету) и т. Д.

Прямо сейчас есть только 'Buys' фильтр. Который будет заселять выбор машины, купленной у каждого студента. Но если 'country' добавляется в модель соло, затем должен быть добавлен фильтр "страна". Каждый дополнительный студент может добавить несколько / много атрибутов в дополнительное поле.

Итак, только 'json_field_property_name' должен быть взят динамическим и передан в новый производный класс для list_filter, Также у нас есть get_list_filter метод из admin.ModelAdminмы можем использовать это для передачи динамически созданного класса. Но я не уверен, как создать класс на лету.

Любая помощь будет оценена.

0 ответов

Другие вопросы по тегам