How do I get a queryset of specific child classes? It doesn't look like going through related_name
is the answer. Using Django 3.2.6 btw.
Here is my setup:
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(...)
What I want is to get a queryset of just MC Questions and process them as such.
I feel the need to emphasize that Question is NOT abstract. So the question model has its own related_name
but the specified '%(class)s'
pattern does not seem to propagate down to the child classes. All the other threads I've seen suggest using that pattern but it only works for abstract models! not when using multi-table inheritance.
From what I've seen, I can't just do:
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()
CodePudding user response:
You can .filter(…)
[Django-doc] with:
MCQuestion.objects.filter(quiz=quiz1)
For inheritance of a concrete model, Django will make tables for the Question
, TFQuestion
and MCQuestion
s, so three tables. The MCQuestion
will have a "hidden" OneToOneField
to Question
.
CodePudding user response:
self answer (kinda)
a couple workarounds i've seen, but jankier than just using a related_name:
A.) using 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.) using InheritanceManager
and 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