Наследование моделей в 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

Мне было бы интересно узнать, есть ли лучшие альтернативы.

Вернуться на верх