Создание динамических классов 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
мы можем использовать это для передачи динамически созданного класса. Но я не уверен, как создать класс на лету.
Любая помощь будет оценена.