Making good progress with my Django project but for this sticking usability issue. I want to be able to filter dropdowns in inline forms based on the parent id. For example.
The Theme model belongs to a course.
class Theme (models.Model):
id = models.AutoField(primary_key=True) # AutoField?
code = models.CharField(max_length=5)
course = models.ForeignKey(Course)
theme_text = models.CharField(max_length=50)
description = models.TextField(blank=True, max_length=1000)
zorder = models.IntegerField()
The indicator model also belongs to a course
class Indicator (models.Model):
id = models.AutoField(primary_key=True) # AutoField?
code = models.CharField(max_length=10)
indicator_text = models.TextField(blank=True)
explained = models.TextField("Explained",blank=True)
course = models.ForeignKey('curriculum.Course')
theme = models.ForeignKey(Theme)
strand = models.ForeignKey(Strand,blank=True,null=True)
level = models.ForeignKey(Level,blank=True,null=True)
concept = models.ManyToManyField(Concept,blank=True)
The admin theme form calls an Indicator Inline
class ThemeAdmin(admin.ModelAdmin):
list_display = ['code', 'theme_text','description','course']
list_filter = ['course']
inlines = [InlineIndicator]
which in turn calls a IndicatorInlineForm
class InlineIndicator(admin.TabularInline):
form = IndicatorInlineForm
model = Indicator
extra = 0
the IndicatorInlineForm filters data to some fields (course, theme, strand and concept)
class IndicatorInlineForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
super(IndicatorInlineForm, self).__init__(*args, **kwargs)
if self.instance.pk is not None:
self.fields['course'].queryset = Course.objects.filter(id=self.instance.course)
self.fields['theme'].queryset = Theme.objects.filter(course=self.instance.course)
self.fields['strand'].queryset = Strand.objects.filter(course=self.instance.course)
self.fields['concept'].queryset = Concept.objects.filter(course=self.instance.course)
else:
self.fields['course'].queryset = Course.objects.filter(id=4)
self.fields['theme'].queryset = Theme.objects.filter(course=4)
self.fields['strand'].queryset = Strand.objects.filter(course=4)
self.fields['concept'].queryset = Concept.objects.filter(course=4)
This is working for existing records where the course id has been set in the indicator record but it is not yet working for new indicator records.
I would like new indicator records to use the course the course.id as per the theme to filter the available options.
I'm not sure I see how the suggested duplicate solves this as it is for existing records or maybe I am wrong in which case help me!
I've been reading about formsets but it feels like it maybe over complicating it. I'm also a bit confused about where it would slot in with what I have already.
Thanks in anticipation of your help (and all the help so far).
Chris
I was able to answer this using formfield-for-foreignkey-and-inline-admin although it does not appear to work for the concept manytomany field.
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
changelist_filters = request.GET['_changelist_filters'].rsplit("=",1)
course_id = int(changelist_filters[1])
if db_field.name == 'course':
kwargs['queryset'] = Course.objects.filter(pk = course_id)
elif db_field.name == 'strand':
kwargs['queryset'] = Strand.objects.filter(course = course_id)
elif db_field.name == 'concept':
kwargs['queryset'] = Concept.objects.filter(course = course_id)
return super(InlineIndicator, self).formfield_for_foreignkey(db_field, request, **kwargs)
I removed the filters from the IndicatorInlineForm as these were no longer required.