quinta-feira, 10 de abril de 2014

Como fazer um filtro personalizado pro admin do Django com o SimpleListFilter

Muitas vezes os filtros automáticos que o admin do django faz são muito úteis. Contudo há momentos que simplesmente colocar o nome do atributo no list_filter não atende. Pra esses momentos temos o SimpleListFilter. 

Ano de Copa, álbuns de figurinhas à venda, suponhamos que, assim como eu, você tenha feito (ou queira fazer)  um sistema pra gerenciamento das figurinhas da Panini.

O models.py ficaria assim:

# coding: utf-8
from django.db import models
class Figurinha(models.Model):
 """(Figurinha description)"""
 numero = models.CharField(max_length=3, verbose_name=u'Número')
 quantidade = models.IntegerField(default=0)
 especial = models.BooleanField(default=False, help_text='Figurinhas brilhantes e/ou diferenciadas')
 data = models.DateTimeField(null=True, blank=True, auto_now=True, verbose_name=u'Modificação')

 class Meta:
  ordering = ('id',)

 def __unicode__(self):
  return self.numero



Algumas explicações antes de continuarmos:

  • Número é sim um CharField, pois neste álbum existem figurinhas alfanuméricas (J1, J2, J3, J4, L1, L2, L3, L4 e W1)
  • Quantidade será o campo atualizável, onde 0 são as figurinhas que faltam, 1 pra colada no álbum e maiores que 1 pra quantidade de repetidas. Ex: Quantidade = 2, são 1 no álbum e 1 repetida.
  • Data será atualizada a cada atualização da figurinha para que seja possível emitir a data da ultima atualização da lista

E o admin.py :

class StatusListFilter(admin.SimpleListFilter):
 # Human-readable title which will be displayed in the
 # right admin sidebar just above the filter options.
 title = 'Status'

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

 def lookups(self, request, model_admin):
  """
  Returns a list of tuples. The first element in each
  tuple is the coded value for the option that will
  appear in the URL query. The second element is the
  human-readable name for the option that will appear
  in the right sidebar.
  """
  return (
   ('falta', 'Falta'),
   ('tenho', 'Tenho'),
   ('repetida', 'Repetida'),
  )

 def queryset(self, request, queryset):
  """
  Returns the filtered queryset based on the value
  provided in the query string and retrievable via
  `self.value()`.
  """
  # Compare the requested value (either '80s' or 'other')
  # to decide how to filter the queryset.
  if self.value() == 'falta':
   return queryset.filter(quantidade=0)
  elif self.value() == 'tenho':
   return queryset.filter(quantidade__gt=0)
  elif self.value() == 'repetida':
   return queryset.filter(quantidade__gt=1)

class FigurinhaAdmin(admin.ModelAdmin):
 search_fields = ('numero',)
 list_display = ('numero','quantidade','especial','data')
 list_filter = ['quantidade','especial','data',StatusListFilter]
 list_editable = ['quantidade',]
 date_hierarchy = 'data'
 readonly_fields = ['numero','especial',]
 save_on_top = True

 fieldsets = (
  (u'Número', {'fields': ('numero',)}),
  ('Quantidade', {'fields': ('quantidade',)}),
  ('Especial', {'fields': ('especial',)}),
 )

admin.site.register(Figurinha, FigurinhaAdmin)


Para mais informações sobre o SimpleListFilter, consulte https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter

hasta!

quinta-feira, 20 de março de 2014

Can't compare offset-naive and offset-aware datetimes

Usando um ambiente com o Django 1.4.3 e  o django-watermark 0.1.6-pre1 o erro :

CAN'T COMPARE OFFSET-NAIVE AND OFFSET-AWARE DATETIMES

Para resolver basta puxar a app watermark para dentro do seu projeto ao invés de usar a instalação do ENV e fazer as seguintes alterações no arquivo watermarker/templatetags/watermark.py:




Na linha 9: Adicione a linha :

from django.utils import timezone




Na linha 155/156: Troque a linha:

if modified >= watermark.date_updated:


Pela linha:

if timezone.make_aware(modified, timezone.get_default_timezone()) >= watermark.date_updated:



hasta!

sexta-feira, 6 de dezembro de 2013

App de cidades e estados brasileiros

Vez ou outra é necessário cadastrar a cidade e o estado em um formulário de algum projeto, seja para cadastro de perfis, pedidos, etc.

Quando tem endereço envolvido ainda é mais fácil, pois existem diversos webservices que fornecem o nome da forma correta, como consta nos correios. O problema acontece quando desejamos apenas cidade e estado.

Sempre aparece alguns "espertinhos" (pra não dizer outra coisa), que escrevem sua cidade cada hora de um jeito, abreviando das mais diversas maneiras, e com isso, o banco fica uma bagunça quando precisa-se filtrar ou tirar um relatório baseado em cidades.

Por isso, resolvi montar um banco com base nas informações dispostas no site do IBGE (http://www.cidades.ibge.gov.br/xtras/home.php - atualizado em 2010) para ajudar com esta tarefa.

Espero que ajude outros programadores.

Segue o link: https://github.com/zejuniortdr/cidades-br

hasta!