Кверисет для конкретного дочернего класса (НЕ абстрактная модель)
Как получить кверисет определенных дочерних классов? Не похоже, что прохождение через 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