Pular para o conteúdo
dicas de djangopor Regis do Python

Dica 5 - Django Admin Date Range filter

3 min de leitura
Assistir ao vídeo no YouTube: Dica 5 - Django Admin Date Range filter

Versões usadas no vídeo: Django 2.2.13, django-daterange-filter 1.3.0 e Python 3.8.2.

Repositório: https://github.com/tzulberti/django-datefilterspec

O list_filter do admin do Django, quando aplicado a um campo de data, só oferece opções fixas: "Qualquer data", "Hoje", "Últimos 7 dias", "Este mês", "Este ano". Para filtrar por um intervalo de datas qualquer (de tal dia até tal dia), usamos a biblioteca django-daterange-filter, que acrescenta ao filtro dois campos de data com calendário.

Esta dica continua a Dica 4: vamos acrescentar o filtro por data de publicação ao admin de artigos.

O repositório da biblioteca está marcado como ABANDONED (abandonado). O aviso aponta para um pull request com mais informações, e o projeto aceita contribuições de quem quiser mantê-lo. Mesmo assim, ele funcionou bem no vídeo, com o Django 2.2.

Pré-requisitos

O projeto das dicas 3 e 4 (myproject, app core, models Article e Category, com os artigos já cadastrados) e o admin.py personalizado na Dica 4.

Instalação

pip install django-daterange-filter
Installing collected packages: django-daterange-filter
    Running setup.py install for django-daterange-filter ... done
Successfully installed django-daterange-filter-1.3.0

Repare que o pacote se chama django-daterange-filter, mas o app é daterange_filter, com underline. Acrescente-o ao INSTALLED_APPS (ele traz um template próprio para o filtro, por isso precisa estar instalado como app):

# settings.py
INSTALLED_APPS = (
    ...
    'daterange_filter'
)

No projeto do boilerplate fica assim:

# myproject/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_extensions',
    'daterange_filter',
    'myproject.core'
]

Usando o DateRangeFilter no admin

Importe o DateRangeFilter:

from daterange_filter.filter import DateRangeFilter

No list_filter, em vez de passar só o nome do campo, passe uma tupla com o nome do campo e a classe do filtro: ('published_date', DateRangeFilter). Os outros filtros continuam funcionando normalmente ao lado:

# admin.py
from daterange_filter.filter import DateRangeFilter

...

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    ...
    list_filter = (
        ('published_date', DateRangeFilter),
        'category',
    )

Atenção às vírgulas: list_filter é uma tupla de filtros, e o primeiro item é ele mesmo uma tupla (campo, filtro).

O admin.py completo, com o que já tínhamos da Dica 4:

# myproject/core/admin.py
from django.conf import settings
from django.contrib import admin
from daterange_filter.filter import DateRangeFilter
from .models import Article, Category
# from .forms import ArticleAdminForm


@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'get_published_date')
    search_fields = ('title',)
    list_filter = (
        ('published_date', DateRangeFilter),
        'category',
    )
    readonly_fields = ('slug',)
    date_hierarchy = 'published_date'
    # form = ArticleAdminForm

    def get_published_date(self, obj):
        if obj.published_date:
            return obj.published_date.strftime('%d/%m/%Y')

    get_published_date.short_description = 'Data de Publicação'


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    actions = None

    def has_add_permission(self, request, obj=None):
        return False

    if not settings.DEBUG:
        def has_delete_permission(self, request, obj=None):
            return False

Resultado

Suba o servidor e abra Artigos no admin:

python manage.py runserver

Na barra lateral Filter aparece, acima de "By categoria", o filtro "By criado em" (o admin do vídeo está em inglês; "criado em" é o verbose_name do campo published_date), com dois campos de data, cada um com o atalho "Today" e o ícone de calendário, e os botões Search e Clear.

No vídeo, todos os artigos foram criados em 14/06/2020:

  • Com o intervalo de 2020-06-16 a 2020-06-25, nenhum artigo é listado.
  • Com o intervalo de 2020-06-14 a 2020-06-25, os 4 artigos aparecem.

O filtro vai para a URL com o prefixo drf__, por exemplo:

/admin/core/article/?drf__published_date__gte=2020-06-14&drf__published_date__lte=2020-06-25

Ou seja, ele usa os lookups __gte (maior ou igual) e __lte (menor ou igual) no campo de data.

Observação: o django-daterange-filter 1.3.0 importa django.contrib.admin.templatetags.admin_static, que foi removido no Django 3.0, por isso ele só funciona até o Django 2.2. Em versões mais novas do Django, use uma alternativa mantida, como o django-admin-rangefilter.

Sugerir uma correção nesta página