Question

I have a model, Challenge_Question:

class ChallengeQuestion(models.Model):
    challenge = models.ForeignKey('Challenge')
    question = models.CharField(max_length=500)
    displayed_answers = models.IntegerField()
    required = models.BooleanField()
    multiple_choice = 'MC'
    fill_in_the_blank = 'FB'
    ordering = 'OR'
    true_false = 'TF'
    question_choices = (
        (multiple_choice, 'Multiple Choice'),
        (fill_in_the_blank, 'Fill In The Blank'),
        (ordering, 'Ordering'),
        (true_false, 'True/False'),
    )
    question_type = models.CharField(max_length=2, choices=question_choices, default=multiple_choice, db_index=True)

For each question_type, I then have a related model FK to ChallengeQuestion:

class ChallengeQuestionMC(models.Model):   #for multiple choice questions
    question = models.ForeignKey('ChallengeQuestion')
    option = models.CharField(max_length=500)
    is_answer = models.BooleanField()

class ChallengeQuestionFB(models.Model):  #for fill-in-the-blank questions
    question = models.ForeignKey('ChallengeQuestion')
    option = models.CharField(max_length=100)
    sequence = models.SmallIntegerField(default=1, blank=True, null=True)

class ChallengeQuestionTF(models.Model):  #for true/false questions
    question = models.ForeignKey('ChallengeQuestion')
    is_correct = models.BooleanField()

class ChallengeQuestionOR(models.Model):  #for ordering type questions
    question = models.ForeignKey('ChallengeQuestion')
    option = models.CharField(max_length=500)
    sequence = models.SmallIntegerField(default=1, blank=True, null=True)

What I would love to do next is have the appropriate admin inline option available for each question, depending on the question_type.

For example if I am filling out a challenge_question that is of True/False type, I want to have the True/False "is_correct" field available to check off or not. And if the question is an ordering type, I want to have Ordering options available with the sequence field along with it. And so on.

If I just add to admin.py:

class ChallengeQuestionOptionsInline(admin.StackedInline):
    model = ChallengeQuestionMC
    extra = 2

class ChallengeQuestionAdmin(admin.ModelAdmin):
    inlines = [ChallengeQuestionOptionsInline]

admin.site.register(ChallengeQuestion, ChallengeQuestionAdmin)

Then this obviously isn't going to work the way I'd like. I need to have some conditional logic here, such as "if challenge_question is question_type 'MC' then use the ChallengeQuestionMC model. And so on.

I'm unable to find anything yet on how such conditional logic might work within a django admin inline... any suggestions?

Was it helpful?

Solution

This code is untested, so it might need tweaking. It seems to me possible, however, that rather than define the inlines globally throughout the ModelAdmin, you can actually set them in the locally by extending the change_view function (this is the view that the admin system uses to change a specific object). It might look something like this:

class MCInline(admin.StackedInline):
    model = ChallengeQuestionMC

class FBInline(admin.StackedInline):
    model = ChallengeQuestionFB

class TFInline(admin.StackedInline):
    model = ChallengeQuestionTF

class ORInline(admin.StackedInline):
    model = ChallengeQuestionOR

class ChallengeQuestionAdmin(admin.ModelAdmin):
    def change_view(self, request, object_id, form_url='', extra_context=None):
        model = self.model
        obj = self.get_object(request, unquote(object_id))

        if obj.question_type == 'MC'
            self.inlines = [MCInline]
        elif obj.question_type == 'FB'
            self.inlines = [FBInline]
        elif obj.question_type == 'TF'
            self.inlines = [TFInline]
        elif obj.question_type == 'OT'
            self.inlines = [ORInline]

        return super(MyModelAdmin, self).change_view(request, object_id,
                    form_url, extra_context=extra_context)

Again, this is untested, so it very well might need some tweaking to work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top