Question: Django admin display filter depending on other filters

Question

Django admin display filter depending on other filters

Answers 2
Added at 2017-11-07 18:11
Tags
Question

Here is an example of models:

class Books(models.Model):
    ...

class Chapter(models.Model):
    ... 
    book = models.ForeignKey('Books')

class Exercise(models.Model):
    ...
    book = models.ForeignKey('Books')
    chapter = models.ForeignKey('Chapter') 

And here is the Admin class for exercise:

class ExerciseAdmin(admin.ModelAdmin):
   ...
   list_filter = (('book',admin.RelatedOnlyFieldListFilter),('chapter',admin.RelatedOnlyFieldListFilter))

admin.site.register(Exercise, ExerciseAdmin)

I now have the filters book and chapter for exercise. When I click on a book in the filter book, it shows me all the exercises of the selected book accordingly. But in the list of filter chapter, it still shows all the chapters of all the books.

Is there a way to only display, in the filter chapter, the chapters of the book that I selected in the first filter book? How?

Answers to

Django admin display filter depending on other filters

nr: #1 dodano: 2017-11-07 21:11

Have you looked at this from the admin documentation https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter with a SimpleListFilter

example in this thread... Creating Custom Filters for list_filter in Django Admin

Guessing here...

from django.contrib.admin import SimpleListFilter

class ChapterFilter(SimpleListFilter):
   title = 'chapter' 
   parameter_name = 'chapter'

   def lookups(self, request, model_admin):
       chapters = set([c.book for c in model_admin.model.objects.all()])
       return [(b.id, b.name) for b in chapters]

   def queryset(self, request, queryset):
       if self.value():
           return queryset.filter(book__id__exact=self.value())

class BookAdmin(ModelAdmin):
    list_filter = (('book',admin.RelatedOnlyFieldListFilter), (ChapterFilter))
nr: #2 dodano: 2017-11-08 00:11

I'm not sure if it's the best way to do it, but here I use the GET parameter of the url from the admin panel to get the ID of the book then I can select the corresponding chapters. And it works!

class ChapterFilter(admin.SimpleListFilter):
    title = 'chapter' 
    parameter_name = 'chapter'
    def lookups(self, request, model_admin):
        if 'book__id__exact' in request.GET:
            id = request.GET['book__id__exact']
            chapters = set([c.chapter for c in model_admin.model.objects.all().filter(book=id)])
        else:
            chapters = set([c.chapter for c in model_admin.model.objects.all()])
        return [(b.id, b.titre) for b in chapters]

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(chapter__id__exact=self.value())

class ExerciseAdmin(admin.ModelAdmin):
   list_filter = (('book',admin.RelatedOnlyFieldListFilter), (ChapterFilter))
Source Show
◀ Wstecz