Morte ao IE 6

O Internet Explorer já deu muita dor de cabeça, principalmente o 6, está na hora de seguir em frente.

Se dependesse apenas de mim, ele já estaria extinto da face da web, ou pelo menos eu não daria suporte a este browser nos meus projetos.

Infelizmente a adoção de browsers novos é lenta, o IE6 vem junto com o XP, muita gente não sai do XP porque o Vista tem lá os seus problemas, um Mac é caro, o Linux é difícil, e por aí vai…

Se você descarta um browser popular, pode se preparar para reclamações e saber que estará perdendo boa parte do seu potencial de acessos.

Então estou aqui para fazer um apelo em nome de todos que trabalham com web, em nome do desenvolvimento da web e em meu próprio nome para que você largue este browser obsoleto e abra a sua mente para novos horizontes.

Para não deixar ninguém na mão, eis algumas opções:

  • utilize o Chrome, powered by Google, um browser extremamente leve e rápido;
  • use o Firefox, não é tão leve quanto o Chrome, mas é altamente customizável através de complementos, seguro e muito mais rápido que qualquer IE;
  • o Opera também é muito bom, bastante leve e rápido, mas como é pouco popular, alguns sites falham nele;
  • nunca usei o Safari, mas pelo que leio parece muito bom, e mesmo se não for, qualquer coisa é melhor que o IE 6;
  • em último caso, se você for muito teimoso, atualize o seu IE 6 para o 7, ele é mais agradável e tem abas!

Para quem quiser aderir ao impeachment do IE, estes links podem ajudar.

http://iedeathmarch.org/
http://ie6.forteller.net/index.php?title=Main_Page

Vídeo: história do Python

Um vídeo mostrando o histórico de commits do Python. Muito interessante.

Gostaria de ver um baseado no Django! 🙂

Vi no VianaWEB.

Python no windows: console, janelas e serviço

Devem fazer uns 10 anos que trabalho com web, não tenho do que reclamar, gosto muito e pretendo continuar por um bom tempo, a não ser que apareça algo que me deixe rico antes.

No começo da minha carreira de desenvolvedor trabalhei com Delphi, MS Access, fiz alguma coisa com Visual Basic, mas nada que me orgulhasse muito. Quem olhar a minha tag cloud  não vai encontrar nenhum destes três, mas com certeza vai encontrar um python tímido, ofuscado por um Django relativamente grande.

Recentemente apareceu um projeto interessante que me deu chance de abrir um pouco a cabeça e de aprender algumas coisas novas.

Como estava enferrujado com programação para desktop, resolvi aproveitar que tenho feito muita coisa em Django e que, por isto, o Python está fresco na minha memória e resolvi utilizá-lo neste projeto. Tirando os detalhes sórdidos do que a ferramenta deveria fazer, eu precisaria desenvolver:

  • um módulo em console (é isso aí: terminal, DOS, tela preta, dir…);
  • outro módulo com interface gráfica (gui, janelinha, botão);
  • e um serviço do windows (aquele que fica escondido e você nunca sabe o que faz).

Fazer uma aplicação em console utilizando o Python não é um problema, então não preciso entrar em muitos detalhes.

Desenvolver uma aplicação com interface gráfica já fica um pouco mais complicado. Meu irmão Ramiro já havia comentado sobre isso e até me mostrou como fazer uma aplicação utilizando PyGTK, mas eu nunca gostei de aplicações baseadas em GTK no Windows, pois os controles são próprios e às vezes têm uma aparência ou comportamento estranhos.

Então eu procurei por algo que me permitisse ter controles nativos do Windows, depois de alguma pesquisa e testes encontrei a biblioteca wxPython, um porte da wxWidgets para Python. Existem muitos exemplos na web, é só achar um parecido com o que você quer e alterar à vontade.

A parte punk mesmo foi fazer um serviço para Windows, se não houvesse uma biblioteca pra auxiliar eu provavelmente largaria os betes. Brincadeira, sempre há uma solução, mas com certeza seria mais porca. Para quem precisar recomendo: Python Extensions for Windows (pywin32).

Por fim, precisei empacotar isso tudo para distribuir de uma maneira amigável sem exigir a instalação do Python, para isso entraram em cena:

  • o py2exe para compilar os scripts e embutir o Python dentro do exe ou de uma biblioteca;
  • e o NSIS para criar um instalador experto e enxuto.

O legal é a flexibilidade e agilidade do python para fazer qualquer coisa. Aprendi muitos truques que posso usar para projetos futuros.

Logo devo postar alguns links e textos sobre esta experiência por aqui, é muita coisa de uma vez só…

Django Sphinx no Windows – preload: failed to open (libmysql.dll)

Para quem pensa em colocar algum tipo de busca em um site com um pouco mais de acesso, aconselho bastante o uso do Sphinx, um indexador pra lá de experto, deixa pra trás as funções de fulltext search do MySQL ou PostgreSQL, o que muito me admira, um projeto independente ter uma performance tão absurdamente melhor do que as ferramentas já conhecidas.

Recentemente estive trabalhando com o Sphinx e com o django sphinx para implementar um sistema de busca dentro de uma ferramenta.

Aliás, parabéns ao David Cramer, o cara faz umas coisinhas muito úteis, ele é o desenvolvedor principal do django sphinx.

Em casa eu uso o Ubuntu, mas no trabalho utilizo o Windows. Baixei a versão do sphinx para windows, instalei e configurei.

Depois disso eu não conseguia rodar o serviço de busca, aparecia a seguinte mensagem:

WARNING: index ‘xxxxx’: preload: failed to open xxxxx.sph: No such file or directory; NOT SERVING

Levei um tempo para descobrir o problema. Ao rodar o indexador, não aparecia nenhuma mensagem de erro, então não me dei conta de que poderia estar ocorrendo algo de errado. Geralmente no Linux quando não há nenhuma mensagem é sinal de que está tudo certo.

Fui procurar pelos arquivos dos índices e não encontrei nenhum, sem índice o serviço não sobe.

Eu estava tentando rodar o indexador pelo console, não sei por que cargas d’água fui rodar o indexador pelo explorer e me apareceu uma mensagem dizendo que não havia encontrado uma DLL do MySQL, a libmysql.dll.

Achei estranho, estava usando o o Sphinx para indexar uma base em PostgreSQL, não faz muito sentido ele reclamar de uma DLL do MySQL, mas tudo bem, não vou chorar.

Encontrei o arquivo, coloquei na pasta dos executáveis (bin) e aí consegui gerar os índices e subir o serviço.

Como não encontrei muita informação, achei interessante deixar a dica por aqui.

UmPortugues.com: site do acordo ortográfico

Olha o jabá…

Meu amigo Aurélio lançou um site para ensinar as novas regras definidas pelo Acordo Ortográfico.

O site é o UmPortugues.com, nele você pode colar um texto qualquer e ver se está de acordo com as novas regras.

O interessante é que ele não apenas diz quais palavras estão erradas, como os corretores ortográficos normais, ele explica, dando exemplos de outras palavras que se encaixam na mesma regra, citando exceções e fazendo referências ao texto oficial do acordo.

Muito bacana, vale conferir!

Pegadinha do Djangão: form não salva Many to Many com commit=False

Lidar com formulário na web costuma ser muito chato, mas os forms do Django ajudam a aliviar esta dor.

Para manipular instâncias de models existe o ModelForm, com ele não é preciso criar todos os campos de um model, ele já cria os controles padrão para cada tipo de campo, é só alimentar o form, ele faz sozinho uma série de validações.

Se precisar manipular a instância antes de salvar no banco, pode usar um commit=False no método save, fazer as manipulações necessárias e salvar novamente.

Mas existe uma pegadinha aí. Se a instância não está sendo salva no banco, não existe uma chave primária ainda, e então não é possível associar os valores selecionados do campo many-to-many.

Consultando o oráculo encontrei a solução no changeset 5804: Fixed #4001 — Added dynamic save_m2m method() to forms created with form_for_model and form_for_instance on save(commit=False).

Tá, tá!! O changeset já tem quase dois anos de idade, mas e daí? Eu não sabia ainda…

Enfim, ao usar o commit=False, é criado no form um método dinâmico save_m2m para salvar as relações many-to-many após salvar uma instância.

Criei um exemplo para simular este comportamento, como estou com preguiça, apenas considere que estou usando um ModelForm com um model que tenha um ManyToMany

def some_view(request):

    if request.method != 'POST':
        form = SomeModelForm()
    else:
        form = form = SomeModelForm(request.POST)
        if form.is_valid():
            # Com o commit=False, a instância é criada mas não é salva no banco
            # Assim é possível alterar antes de salvar no banco.
            instance = form.save(commit=False)

            # Salva o usuário atual como autor da instância
            instance.author = request.user
            instance.save()

            # Se o form tiver algum campo M2M e for usado o commit=False,
            # ficará disponível o método save_m2m, que associa os valores
            # selecionados à instância recém-criada.

            # NOTA: vale lembrar que este método é criado dinamicamente,
            # ou seja, não é seguro executá-lo sempre ao salvar um form.

            if hasattr(form, 'save_m2m'):
                form.save_m2m()

            # Redireciona para a página de sucesso
            return HttpResponseRedirect('./ok/')

    context = {'form': form}

    return render_to_response('some_template.html', context)

UPDATE 09/02/2009: corrigida verificação de GET/POST, graças ao Igor Sobreira.