skip to Main Content

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()

2

Answers


  1. Chosen as BEST ANSWER

    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
    

  2. 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 MCQuestions, so three tables. The MCQuestion will have a "hidden" OneToOneField to Question.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search