Пользовательский фильтр для поля даты в Django Admin, Django 1.2

Это все еще действующий синтаксис для Django 1.2?

Пользовательский фильтр в Django Admin в Django 1.3 или ниже

Я пробовал, но параметр list_filter в классе администратора не распознает мой настраиваемый фильтр. Как добавить настраиваемый фильтр в list_filter, чтобы он отображался?

    class MyModelAdmin(admin.ModelAdmin):
        ...
        list_filter = ['is_expired_filter']

Здесь мой is_expired_filter - это мой недавно зарегистрированный настраиваемый фильтр, который, по словам автора, ему нравится:

    list_filter = ('is_live')

Но это не распознается Django, и ошибка, которую я получаю при загрузке страницы администратора,

Тип исключения: ImproperlyConfigured Значение исключения: «PositionAdmin.list_filter [2]» относится к полю «is_expired_filter», которое отсутствует в модели «Position»

Возможно, моя ошибка в том, что я не уверен, как автор этого вопроса использует исходный код после того, как он / она реализует собственный фильтр.

Вот исходный код:

    def is_live(self):
        if self.when_to_publish is not None:
            if ( self.when_to_publish < datetime.now() ):
                return """ <img alt="True" src="/media/img/admin/icon-yes.gif"/> """
        else:
            return """ <img alt="False" src="/media/img/admin/icon-no.gif"/> """      

    is_live.allow_tags = True

person user773328    schedule 27.05.2011    source источник
comment
Вы прочитали ответ на предоставленную ссылку или просто вопрос?   -  person Bryce Siedschlaw    schedule 27.05.2011
comment
Тщательно, как и соответствующий django API, но что-то ускользает от меня. Пожалуйста, будьте добры и дайте мне знать, что я упустил.   -  person user773328    schedule 27.05.2011
comment
Является ли ваш is_expired_filter полем в вашей модели?   -  person Bryce Siedschlaw    schedule 27.05.2011
comment
Кроме того, какое поле (поля) предполагается фильтровать, если это не поле модели? Было бы неплохо побольше информации.   -  person Bryce Siedschlaw    schedule 27.05.2011
comment
Единственная проблема в том, что я не думаю, что is_expired_filter - это поле. Я думаю, он хочет, чтобы это был настраиваемый фильтр, основанный на нескольких полях.   -  person Bryce Siedschlaw    schedule 27.05.2011
comment
Я ценю ваши попытки понять мой вопрос до сих пор. Возможно, вопрос в том, как подключить настраиваемый фильтр к полю в модели? Пользовательский фильтр основан только на одном поле, он является подклассом DateFieldFilterSpec и определен в файле filters.py в соответствии с Django API / предыдущим ответом.   -  person user773328    schedule 27.05.2011


Ответы (2)


Теперь, когда у меня есть представление о том, что, как мне кажется, вы хотите, я предполагаю, что у вас есть модель, которую вы хотите отфильтровать по DateField, например:

class Position(models.Model):
    expiration_date = models.DateField()
    ...

который вы должны теперь изменить на

class Position(models.Model):
    expiration_date = models.DateField()
    expiration_date.is_expired_filter = True
    ...

Что вы хотите сделать, так это добавить в свой admin.py новый класс фильтра

from django.contrib.admin.filterspecs import FilterSpec, DateFieldFilterSpec
from django.utils.translation import ugettext as _
from datetime import datetime, date
class ExpiredFilterSpec(DateFieldFilterSpec):
    """
    Adds filtering by future and previous values in the admin
    filter sidebar. Set the is_expired_filter filter in the model field
    attribute 'is_expired_filter'.
    my_model_field.is_expired_filter = True
    """
    def __init__(self, f, request, params, model, model_admin, **kwargs):
        super(ExpiredFilterSpec, self).__init__(f, request, params, model,
                                                model_admin, **kwargs)
        today = date.today()
        self.links = (
            (_('All'), {}),
            (_('Not Expired'), {'%s__lt' % self.field.name: str(today),
                   }),
            (_('Expired'), {'%s__gte' % self.field.name: str(today),
                    }))
    def title(self):
        return "Filter By Expiration Date"
# registering the filter
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_expired_filter', False),
                                   ExpiredFilterSpec))


class PositionAdmin(admin.ModelAdmin):
    list_filter = ['expiration_date']
person dr jimbob    schedule 27.05.2011
comment
Спасибо за ответ. Когда я попробовал в пятницу, это не сработало. Новый настраиваемый фильтр появился на странице администратора, но на самом деле он не работал, поэтому, когда вы щелкнули по одному из вариантов (варианты «Срок действия истек» или «Срок действия не истек» в случае приведенного здесь примера), ничего изменено в списке объектов. Завтра попробую еще раз на свежем и чистом проекте. - person user773328; 29.05.2011
comment
Хорошо, просто попробовал именно так; и это не сработало, в основном из-за сравнения DateField с datetime.now() (он давал флаг? e = 1). Когда я пробовал раньше, я настраивал его на что-то полезное для себя. Так что измените today = datetime.now() на date.today(), и все должно быть в порядке. (Убедитесь, что from datetime import date тоже существует.) - person dr jimbob; 29.05.2011
comment
Большое спасибо! Это прекрасно работает. Я внес одно изменение: я явно установил для необязательного аргумента ключевого слова значение None, чтобы я не получал ошибку типа. Я изменил (f, request, params, model, model_admin) на (f, request, params, model, model_admin, field_path=None). Я много узнал о том, как читать и использовать исходный код Django в этом деле. - person user773328; 30.05.2011
comment
@ user773328: Нет проблем. У меня не было этой ошибки; но решил, что имеет смысл просто добавить **kwargs в конец параметров функции __init__ и вызова функции super __init__. - person dr jimbob; 31.05.2011

Почти копируя ссылку Пользовательский фильтр в Django Admin на Django 1.3 или ниже слово в слово, Я это придумал.



from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec, DateFieldFilterSpec
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext as _
from datetime import datetime

class IsExpiredFilterSpec(DateFieldFilterSpec):
    """
    Adds filtering by future and previous values in the admin
    filter sidebar. Set the is_expired_filter filter in the model field 
    attribute 'is_expired_filter'.
    my_model_field.is_expired_filter = True
    """

    def __init__(self, f, request, params, model, model_admin):
        super(IsExpiredFilterSpec, self).__init__(f, request, params, model,
                                                   model_admin)
         # -- You'll need to edit this to make it do what you want. --
#        today = datetime.now()
#        self.links = (
#            (_('Any'), {}),
#            (_('Yes'), {'%s__lte' % self.field.name: str(today),
#                       }),
#            (_('No'), {'%s__gte' % self.field.name: str(today),
#                    }),
#            
#        )


    def title(self):
        return "Is Expired"

\# registering the filter
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_expired_filter', False),
                                   IsExpiredFilterSpec))

class MyModelAdmin(admin.ModelAdmin):
    ...
    MODEL_FIELD_TO_FILTER.is_expired_filter = True
    list_filters = ['MODEL_FIELD_TO_FILTER']

ОБНОВЛЕНИЕ: внесены изменения благодаря jimbob. MODEL_FIELD_TO_FILTER - это поле, которое вы хотите отфильтровать.

person Bryce Siedschlaw    schedule 27.05.2011
comment
Просто обратите внимание: все, что выше MyModelAdmin, можно поместить в ваш файл filters.py - person Bryce Siedschlaw; 27.05.2011
comment
Спасибо. Просто быстрый вопрос, пока я пробую это - не следует ли мне указывать в файле filter.py имя поля DateTime? Если нет, то как они узнают, с каким полем даты и времени сравнивать? - person user773328; 27.05.2011
comment
Это то, что я не мог понять ... Похоже, что переменная f, передаваемая в init, содержит имя поля ... но я не уверен, как она узнает, в каком поле искать если вы не сделали что-то вроде self.fields ['MYFIELD']. is_expired_filter = True - person Bryce Siedschlaw; 27.05.2011
comment
+1. Это почти все. Предполагая, что DateField, по которому выполняется фильтрация, называется expiration_date, вы хотите добавить к определению модели expiration_date.is_expired_filter = True, тогда в ModelAdmin укажите list_filter = ['expiration_date']. - person dr jimbob; 27.05.2011
comment
Спасибо, внес изменения. - person Bryce Siedschlaw; 27.05.2011