django admin list_filter подмножество внешнего ключа

В настоящее время у меня настроена такая модель:

У меня есть класс Test с внешним ключом к пользовательскому классу UserProfile. Это свойство называется student. Таким образом, каждый UserProfile мог занимать более одного Test. Затем, в свою очередь, каждый UserProfile связан с User типичным отношением "один к одному". Добавляется еще один уровень сложности, потому что я объявил две группы пользователей tutors и students. И класс UserProfile имеет отношение ManyToMany к самому себе, помеченному как "репетиторы". Логика такова, что у каждого ученика может быть много наставников. Теперь я хотел бы добавить фильтры в правой части страницы администратора теста, которые позволяют фильтровать по ученику и фильтровать по наставнику. настройка list_filter = ('student',) просто перечисляет все доступные профили пользователей. Но это будет включать в себя UserProfiles, которые также привязаны к репетиторам. Очевидно, я хотел бы отфильтровать этот список только до студентов, потому что явная фильтрация любым из этих наставников приведет к пустому набору запросов. Затем я хотел бы сделать то же самое с фильтрацией по наставнику, где в этом случае сокращение будет list_filter = ('student__tutors'), но я бы хотел, чтобы этот набор UserProfile был отфильтрован, чтобы включить только те, где user_ groups _name = 'репетиторы'. Как лучше всего это сделать?

Для наглядности моя объектная модель выглядит так:

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True,related_name='profile')
    tutors = models.ManyToManyField("self",related_name="students")
class Test(models.Model):
    student = models.ForeignKey(UserProfile,related_name='tests')

Я пробовал создать подкласс django.contrib.admin.SimpleListFilter следующим образом:

class StudentListFilter(SimpleListFilter):
    title = 'student'
    parameter_name = 'student__id__exact'
    def lookups(self, request, model_admin):
        qs = model_admin.queryset(request)
        return User.objects.filter(profile__id__in=qs.values_list('student__id')).extra(select={'full_name':'first_name||" "||last_name'}).values_list('profile__id','full_name')

    def queryset(self, request, queryset):
        if self.value() is not None:
            return queryset.filter(student__id__exact=self.value())
        else:
            return queryset

Кажется, это работает для первого list_filter, но проблема в том, что по какой-то причине теперь есть ошибка, когда выбранный параметр не выделяется в настраиваемом фильтре. Подсвечиваются только «Все», но не настраиваемые параметры. Вот пример того, что опубликовал другой пользователь:

http://imgur.com/lyrYk

В настоящее время я использую разрабатываемую версию django 1.4, поэтому я не уверен, связана ли эта проблема с этим или нет.


person ecbtln    schedule 26.01.2012    source источник


Ответы (1)


Интересная проблема.

Я думаю, вам нужно преобразовать ваш lookups в строку.

return [(str(x), y) for x, y in your_valuesqueryset]

Строка 98 на django.admin.filters определяет выбранный фильтр как:

'selected': self.value() == lookup

Где поиск заполняется непосредственно из результатов метода lookups.

Автоматическое приведение типа в вашем filter() вызове делает фильтр успешным, но '2' != 2

person Yuji 'Tomita' Tomita    schedule 26.01.2012
comment
отличное спасибо. Я предполагаю, что есть отличный способ сделать это на уровне базы данных без понимания списка? в любом случае, наверное, не имеет значения - person ecbtln; 26.01.2012
comment
думал как конкретный вызов SQL, который я мог бы добавить в дополнительный (select =) словарь, чтобы преобразовать столбец первичного ключа int в строку. ну, наверное, это не более эффективно - person ecbtln; 26.01.2012