Фильтрование в админке по полю дочерней модели

Рейтинг: 0Ответов: 1Опубликовано: 08.12.2014

Уже много раз сталкивался с этой проблемой и всегда старался как-то обойти ее. Но сейчас решил уже разобраться наконец.

Есть 2 модели.

models.py

class Obj(model.Model)
    title = models.CharField(...)

def info(self):
    return ObjInfo.objects.get_or_create(obj=self)[0]

def is_paid(self):
    return self.info().paid

class ObjInfo(model.Model):
    obj = models.ForeignKey('Obj')
    paid = models.BooleanField()

admin.py

...
list_filter = ['is_paid', ]
...

Ну и выдает понятное дело:

(admin.E116) The value of 'list_filter[3]' refers to 'is_paid', which does not refer to a Field.

Ответы

▲ 4Принят

list_filter не умеет работать с кастомными методами модели. Ему нужно передавать только реальные поля из модели. В вашем случае это будет 'objinfo__paid'.

Но это может оказаться не очень верно, так как при вашей структуре моделей у Obj может быть несколько ObjInfo с разными paid, и фильтр в таком случае вам найдет этот Obj при любом значении.

Если же в фильтре все таки нужно организовать свою логику, воспользуйтесь кастомными фильтрами django-админки

Выглядит это примерно так:

from django.contrib import admin

class IsPaidListFilter(admin.SimpleListFilter):
    title = 'Is paid'
    parameter_name = 'is_paid'

    def lookups(self, request, model_admin):
        return (
            ('yes', 'Yes'),
            ('no', 'No'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'yes':
            return queryset.filter(...) #  Фильтруете как угодно
        if self.value() == 'no':
            return queryset.filter(...) #  Фильтруете как угодно