Как вернуть все объекты в QuerySet в форме их подкласса, а не в форме родительского класса? - PullRequest
1 голос
/ 12 июня 2019

У меня есть класс Set с отношением "многие ко многим" к Item.У меня есть много «установленных» объектов, все из которых содержат много «предметов».

Однако класс Item был разделен на подклассы для создания Article, Podcast, Video и Episode.По сути, все в базе данных изначально было Предметом.Если my_set является экземпляром Set, содержащим Items - как мне создать Queryset, который возвращает эти объекты в форме их подкласса?Т.е. вместо того, чтобы получать Queryset, полный экземпляров Item, я получаю Queryset с Article, Episode, Video, Podcast экземплярами.

Как бы получить `my_set.objects.all (). as_subclass () 'для работы?

class Item(models.Model, AdminVideoMixin):
   base_attributes = 'foo'

     def as_episode(self):
       return Episode.objects.get(slug=self.slug)

class Video(Item): 
   class specific fields

class Article(Item):
   class specific fields

class Podcast(Item):
   class specific fields

class Episode(Item):
   class specific fields

class Set(Item):
    front_page = models.BooleanField(max_length=300, blank=False, default=False, null=False)
    items = models.ManyToManyField(Item, related_name='in_sets', through='SetMeta', max_length=5000,)

    def get_absolute_url(self):
        return reverse('foo')

    def ordered(self):
        return self.items.all().order_by('-itemOrder__order')

    def episodes(self):
        episode_list = []
        for each_item in self.items.all():
           episode_list.append(each_item.as_episode())
        return episode_list


    def __str__(self):
        return self.title

Как вы можете видеть, я попробовал два метода - написать метод модели для Item (), который возвращает себя как Episode - но это работало только дляотдельные экземпляры, а не Queryset.Поэтому я написал метод для Set, который может выполнять этот метод для всех элементов внутри себя, но он не производит Queryset, просто список, и он кажется грязным?

1 Ответ

1 голос
/ 12 июня 2019

Обновление: только что снова просмотрели django-polymorphic документацию , и похоже точно , что вы хотите.Поэтому остальная часть моего ответа, вероятно, не очень полезна, если только вам не запрещено извлекать код из django-пакетов

. Я не думаю, что Django предоставляет способ выражения набора запросов, которыйвозвращает объекты более чем одного типа модели.Наборы запросов должны отображать inro SQL-запросы, и я не думаю, что SQL может возвращать строки из более чем одной таблицы, смешанной.(Я не эксперт по SQL, поэтому могу ошибаться).Однако, если вам не нужен список, Python предоставляет средство для получения набора запросов и применения преобразования к каждому возвращаемому экземпляру Item: функции генератора.Так, например, вы могли бы кодировать

 def items_as_subclasses(qs):
     for instance in qs:
         try:
             yield instance.video
             continue
         except Video.DoesNotExist:
             pass
         try:
             yield instance.article
             continue
         except Article.DoesNotExist:
              pass

         try: ...

         raise ProbableCodingError(
            f"Item instance id={instance.id} does not have a known subclass"
         )

и затем писать

for item_subclass_instance in items_as_subclasses(queryset):
    # whatever

или действительно передавать "items":items_as_subclasses( queryset) в контекст рендеринга шаблона.

Если естьдлинный список возможных подклассов, возможно, было бы лучше иметь поле subclass_type в базовом классе и использовать его, чтобы перейти прямо к единственному действительному полю подкласса.для его конкретного подкласса, так что вы можете написать наборы запросов, которые опрашивают подклассы.

Или вы можете исследовать django-polymorphic , который я однажды просмотрел и который я смутно помню, предназначен для такого рода использования.

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