David
David

Reputation: 524

Multiple Inlines in Model Admin in Django

I have some models as follows:

models.py

   from django.db import models
    
    SET_CHOICES = [
            ('A', 'Set A'),
            ('B', 'Set B'),
            ('C', 'Set C'),
            ('D', 'Set D')
        ]
    
    class Exam(models.Model):
        exam_name = models.CharField(max_length=255)
        sub_code =  models.CharField(max_length=10)
        sub_name = models.TextField()
        max_marks = models.PositiveIntegerField()
        def __str__(self):
            return f'{self.sub_code}: {self.sub_name}'
    
    class ExamSet(models.Model):
        which_exam = models.ForeignKey(Exam,on_delete=models.CASCADE)
        set_name = models.CharField(
            max_length=1,
            choices=SET_CHOICES,
            default='A',
        )
    
        def __str__(self):
            return f'{self.which_exam.sub_code}: {self.which_exam.sub_name} (Set {self.set_name})'
    
    class Question(models.Model):
        for_which_exam_set = models.ForeignKey(ExamSet, on_delete=models.CASCADE) 
        question_order = models.PositiveIntegerField(blank=True)
        question_text = models.TextField()
        max_marks = models.PositiveIntegerField()
    
        def __str__(self):
            return f'{self.for_which_exam_set}: {self.question_text}'
    
    
    class Choices(models.Model):
        choice_text = models.TextField()
        is_correct = models.BooleanField()
        for_which_question = models.ForeignKey(Question, on_delete=models.CASCADE)

admin.py

from django.contrib import admin
from django.forms import TextInput, Textarea
from django.db import models
from .models import Exam, ExamSet, Question, Choices

# Register your models here.
class QuestionInline(admin.TabularInline):
    model = Question
    extra = 0
    ordering = ("question_order",)
    formfield_overrides = {
        models.TextField: {'widget': Textarea(attrs={'rows':3, 'cols':50})},
    }
    

class ChoicesInline(admin.TabularInline):
    model = Choices
    extra = 0
    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'size':'20'})},
        models.TextField: {'widget': Textarea(attrs={'rows':2, 'cols':30})},
    }

class QuestionAdmin(admin.ModelAdmin):
    list_display = ('question_text', 'max_marks', )
    inlines = [
        ChoicesInline
    ]
    formfield_overrides = {
        models.TextField: {'widget': Textarea(attrs={'rows':3})},
    }
    
    
class ExamSetAdmin(admin.ModelAdmin):
    inlines = [
    QuestionInline
    ]
    

admin.site.register(ExamSet, ExamSetAdmin)

admin.site.register(Question, QuestionAdmin )
admin.site.register(Exam)

And this gives the model inline something like the following: enter image description here

But what I wanted is to have the choices as well for each question in the ExamSet. So,

How to keep the choices also in the inline of questions and questions with the choices in the inline of examsets?

I also should be able to add questions with the choices.

Any help would be useful.

Upvotes: 1

Views: 4023

Answers (1)

David
David

Reputation: 524

As per @minglyu's comments, I have found a solution using the django-nested-admin. In case, anyone in future looking for such features, I have added the admin.py here.

Please make sure that you have installed django-nested-admin with

pip install django-nested-admin

and then, add the app in installed app like

INSTALLED_APPS = [
    ....
    'nested_admin',
    ...
]

Then finallly, in the admin.py, I have changed the code as follows for my Examset admin.

from django.contrib import admin
from django.forms import TextInput, Textarea
from django.db import models
from nested_admin import NestedModelAdmin, NestedTabularInline
from .models import Exam, ExamSet, Question, Choices

# Register your models here.

class ChoicesInline(NestedTabularInline):
    model = Choices
    extra = 0
    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'size':'20'})},
        models.TextField: {'widget': Textarea(attrs={'rows':2, 'cols':50})},
    }

class QuestionInline(NestedTabularInline):
    model = Question
    extra = 0
    inlines = [ChoicesInline]
    ordering = ("question_order",)
    formfield_overrides = {
        models.TextField: {'widget': Textarea(attrs={'rows':3, 'cols':50})},
    }

class ExamSetAdmin(NestedModelAdmin):
    inlines = [
    QuestionInline
    ]
    

admin.site.register(ExamSet, ExamSetAdmin)

Thanks!

Upvotes: 4

Related Questions