Кверисет для конкретного дочернего класса (НЕ абстрактная модель)

Как получить кверисет определенных дочерних классов? Не похоже, что прохождение через related_name является ответом. Использую Django 3.2.6 btw.

Вот моя установка:

class Quiz(models.Model):
    name = # char field

class Question(models.Model):
    # a quiz has many questions
    quiz = models.ForeignKey(Quiz, related_name = '%(class)s')
    # etc...

class TFQuestion(Question):
    is_true = models.BooleanField(...)

class MCQuestion(Question):
    n_choices = models.IntegerField(...)

Я хочу получить набор вопросов, состоящий только из вопросов MC и обработать их как таковые.

Я чувствую необходимость подчеркнуть, что вопрос НЕ является абстрактным. Поэтому модель вопроса имеет свою собственную модель related_name, но указанный паттерн '%(class)s' не распространяется на дочерние классы. Все другие темы, которые я видел, предлагают использовать этот паттерн, но он работает только для абстрактных моделей! не при использовании многотабличного наследования.

Из того, что я видел, я не могу просто сделать:

quiz1 = Quiz.objects.get(id=1)

# this works; returns queryset of Question objects
allquestions = quiz1.question.all()

# doesn't work
all_mcqs = quiz1.mcquestion.all()

Вы можете .filter(…) [Django-doc] с:

MCQuestion.objects.filter(quiz=quiz1)

Для наследования конкретной модели Django сделает таблицы для Question, TFQuestion и MCQuestion, таким образом три таблицы. У MCQuestion будет "скрытая" OneToOneField к Question.

Самостоятельный ответ (вроде как)

я видел несколько обходных путей, но они более неудобны, чем просто использование related_name:

A.) используя classname__isnull:


quiz1 = Quiz.objects.get(id=1)

# get quiz1's MCQuestions as Questions
qs1 = quiz1.question.filter(mcquestion__isnull = False)
# returns: <QuerySet[<Question>,...]>
qs1.first().mcquestion.n_choices

B.) используя InheritanceManager и classname__isnull:

from model_utils.managers import InheritanceManager

class Question(models.Model):
    # ...
    objects = InheritanceManager()

# django shell

quiz1 = Quiz.objects.get(id=1)

# get quiz1's MCQuestions as MCQuestions
qs1 = quiz1.question.select_subclasses().filter(mcquestion__isnull = False)
# returns: <InheritanceQuerySet[<Question>,...]>
qs1.first().n_choices
Вернуться на верх