Наследование моделей в Django с помощью прокси-классов
У меня есть прокси-классы, которые были созданы в основном для реализации пользовательской фильтрации, но есть и некоторые другие довольно небольшие пользовательские методы, и они будут расширены для обеспечения другой пользовательской логики.
Допустим, у меня есть модели:
class Videos(models.Model):
title = models.CharField(max_length=200)
publisher = models.Charfield(max_length=100)
release_date = models.DateField()
class Superheroes(Videos):
objects = SuperheroesManager()
class Meta:
proxy = True
class Recent(Videos):
objects = RecentManager()
class Meta:
proxy = True
и менеджеры моделей:
class SuperheroesManager():
def get_queryset(self):
return super().get_queryset().filter(publisher__in=['Marvel','DC'])
class RecentManager():
def get_queryset(self):
return super().get_queryset().filter(release_date__gte='2020-01-01')
На фронт-энде пользователь может выбрать категорию, которая соответствует одному из прокси-классов. Каким образом лучше всего поддерживать соответствие между категорией, которая передается в представление, и связанным с ней прокси-классом?
В настоящее время у меня есть неявная зависимость, при которой имя категории, предоставляемое фронт-эндом, должно совпадать с именем класса прокси, что позволяет использовать стандартный интерфейс в представлении:
def index(request, report_picked)
category = getattr(sys.modules[__name__], report_picked)
videos = category.objects.all()
Я бы хотел уйти от этой неявной зависимости, но не уверен, что это лучший способ.
Я не хочу поддерживать словарь и не могу использовать метод фабрики, так как он должен возвращать полностью инициализированный объект, тогда как мне нужен только возвращаемый класс.
Каким образом лучше всего это реализовать?
Я могу понять ваше нежелание поддерживать словарь. Однако я не вижу способа сопоставления категории с менеджером без него. Таким образом, этот ответ действительно включает словарь, но я постарался сохранить код настолько простым и DRY, насколько это возможно.
class Videos(models.Model):
title = models.CharField(max_length=200)
publisher = models.Charfield(max_length=100)
release_date = models.DateField()
reports = {}
reports['recent'] = RecentManager()
reports['superheroes'] = SuperheroesManager()
# ...
Для выбора категории можно использовать categories = Videos.reports.keys()
, при этом категории будут перечислены в том же порядке, в котором они были вставлены в словарь. Чтобы перейти к отчету, вы можете сделать, например, videos = Videos.reports[category].all()
.
Если это не совсем соответствует вашим потребностям, возможно, вы сможете использовать это хотя бы в качестве отправной точки.
Я решил задать имя категории, используемое фронт-эндом, в качестве переменной класса:
class Superheroes(Videos):
category = 'superheroes'
objects = SuperheroesManager()
class Meta:
proxy = True
Поэтому представление просто перебирает все модели и возвращает ту модель, категория которой совпадает с предоставленным значением из фронт-энда:
from django.apps import apps
def index(request, report_picked):
for model in apps.get_models():
try:
print(f"Report picked: {report_picked}, model: {model.name}")
if model.category == report_picked.lower():
category = model
break
except AttributeError:
pass
Мне было бы интересно узнать, есть ли лучшие альтернативы.