Simplelistfilter По Умолчанию

У меня есть логическое поле в моей модели, представляет ли кто-то отменил свое членство или нет. Я пытаюсь создать пользовательский SimpleListFilter, который позволяет фильтровать это поле.

однако я действительно хочу показать только тех, кто не отменен по умолчанию. Есть ли способ выбрать опцию " Нет " по умолчанию? Это мой фильтр до сих пор:

class CanceledFilter(SimpleListFilter):

    title = 'Canceled'

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'canceled'

    def lookups(self, request, model_admin):
        return (
            (True, 'Yes'),
            (False, 'No'),
        )

    def queryset(self, request, queryset):

        if self.value() is True or self.value() is None:
            return queryset.filter(canceled=True)
        if self.value() is False:
            return queryset.filter(canceled=False)

изменить: Я должен был выразиться яснее. Я специально пытаюсь сделать это в Admin взаимодействие. Когда я добавляю вышеуказанный фильтр в качестве list_filter в admin. Я получаю фильтр на стороне страницы администратора с 3 вариантами: все, да и нет.

Я хотел бы, чтобы выбор" нет " или ни один из вариантов не был установлен по умолчанию. Вместо этого выбор " все " всегда устанавливается по умолчанию. Есть ли какой-то нет hacky способ установить выбор фильтра по умолчанию или что-то в этом роде.

Basiclly в Admin когда они просматривают членов, Я только хочу показать активный (не отмененный) по умолчанию. Если они нажимают "все" или "Да", затем я хочу показать отмененные.

обновление: Обратите внимание, что это то же самое, что и вопрос фильтр по умолчанию в Django admin, но я этот вопрос сейчас 6 лет. Принятый ответ отмечен как требующий Django 1.4. Я не уверен, что этот ответ по-прежнему будет работать с новыми версиями Django или по-прежнему является лучшим ответом.

учитывая возраст ответы на другой вопрос, я не уверен, как мы должны действовать. Я не думаю, что есть любой способ объединить их.

2 ответов


пришлось сделать то же самое и наткнулся на ваш вопрос. Вот как я исправил его в своем коде (адаптированном к вашему примеру):

class CanceledFilter(SimpleListFilter):

title = 'Canceled'

# Parameter for the filter that will be used in the URL query.
parameter_name = 'canceled'

def lookups(self, request, model_admin):
    return (
        (2, 'All'),
        (1, 'Yes'),
        (0, 'No'),
    )

def queryset(self, request, queryset):

    if self.value() is None:
        self.used_parameters[self.parameter_name] = 0
    else:
        self.used_parameters[self.parameter_name] = int(self.value())
    if self.value() == 2:
        return queryset
    return queryset.filter(cancelled=self.value())

требуется некоторое объяснение. Строка запроса является только частью URL-адреса, и именно то, что подразумевает имя: запрос строка. Ваши значения поступают как строки, а не как логические или целые числа. Поэтому, когда вы звоните self.value() возвращает строка.

если вы изучите URL, который вы получаете при нажатии на Да / нет, если не использовать пользовательский фильтр списка, вы увидите, что он кодирует его как 1/0, а не True / False. Я последовал той же схеме.

для полноты и наших будущих читателей, я также добавил 2 для всех. Без проверки, я предполагаю, что это было None раньше. Но!--3--> также используется, когда ничего не выбрано, по умолчанию все. Кроме того, в нашем случае он должен по умолчанию False, поэтому мне пришлось выбрать другое значение. Если вам не нужна опция Все, просто удалите окончательный if-блок в queryset метод, и первый Кортеж в lookups метод.

С этим в стороне, как это работает? Фокус в том, чтобы понять, что self.value() просто возвращает:

self.used_parameters.get(self.parameter_name, None)

который является либо строкой, либо None в зависимости от того, находится ли ключ в словаре или нет. Итак, это центральная идея: мы удостоверяемся, что он содержит целые числа, а не строки, так что self.value() может использоваться в вызове queryset.filter(). Специальный режим для значения для всех, которое 2: в этом случае просто верните queryset вместо отфильтрованного набора запросов. Другое специальное значение -None, что означает, что нет ключа parameter_name в словарь. В этом случае, мы создаем с значением 0, так что False становится значением по умолчанию.

Примечание: ваша логика была неправильной там; вы хотите, чтобы не отменен по умолчанию, но вы лечите None аналогично True. Моя версия исправляет это.

ps: да, вы можете проверить 'True' и 'False' а не True и False в своем querystring метод, но тогда вы заметите, что правильный выбор не будет выделен, потому что первые элементы в вашем кортеже не совпадают (вы сравниваете строки с логическими значениями). Я попытался сделать первые элементы в строках кортежей, но тогда мне пришлось бы сделать сравнение строк или eval в матче 'True' to True, что является уродливым / небезопасным. Поэтому лучше придерживаться целых чисел, как в моем примере.


посмотрите раздел под названием "добавление дополнительных методов менеджера"в ссылке ниже:

http://www.djangobook.com/en/2.0/chapter10.html

Вы можете добавить дополнительные модели.Менеджер к вашей модели, чтобы только вернуть людей, которые не отменили свое членство. Грубая реализация дополнительных моделей.Менеджер будет выглядеть так:

class MemberManager(models.Manager):
  def get_query_set(self):
    return super(MemberManager, self).get_query_set().filter(membership=True)

class Customer(models.Model):
  # fields in your model
  membership = BooleanField() # here you can set to default=True or default=False for when they sign up inside the brackets

  objects = models.Manager  # default Manager
  members = MemberManager() # Manager to filter for members only

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

Customer.members.all()