'Django - Add classes to inline only if qs len is more than 5

For TaskInline I'd like to display it collapsed if there are more than 5 elements:

from django.contrib import admin
from django.contrib.auth.models import User
from django.db import models


class Task(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField()
    performer = models.ForeignKey(User, on_delete=models.CASCADE)


class TaskInline(admin.TabularInline):
    model = Task

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if len(qs) > 5:
            self.classes = 'collapse',
        return qs


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    inlines = TaskInline,

But trick that is implemented in get_queryset method seems not working (it seems this method selects all the items of Task model).

Where should I compare len to add classes?



Solution 1:[1]

There's no "proper" way to do so, but... To achieve what you want you can pick any method that accepts obj argument. Like has_view_permission or get_forms or get_formset or get_extra...

Note that you will not receive a QuerySet of the related manager, but instead will get the obj that is requested in the non-inline admin.

Example:


class TaskInline(admin.TabularInline):
    model = Task

    def has_view_permission(self, request, obj=None, **kwargs):
        # None for new instances or non object-specific calls
        if obj is not None:  
            # print(obj) -> instance that has Task as inline
            # TODO: fix the following line, because your field might be called differently
            if obj.tasks.count() >= 5:  
                self.classes = list(type(self).classes or []) + ["collapse"]
        return super().has_view_permission(request, obj=obj, **kwargs)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Art