Python logging em Django

Postado por Rafael Sierra em 3/11/2009

Que o módulo logging e o framework Django são excelentes ferramentas pra qualquer trabalho todos sabem, mas como fazer para integrar os dois?

Eu sempre achei um saco o fato do Django não ter um módulo builtin/contrib que permitisse que ao fazer um simples logging.error('PAN!') a mensagem, a data, o nível, the universe and everything, fossem gravados no banco de dados. Pra resolver esse simples problema, nada como uma simples solução.

Solução
A Solução

Para começar crie um aplicativo em sua aplicação chamado "log", nunca crie a aplicação com nome de "logging", a não ser que você queira problemas com imports não funcionando:

python manage.py startapp log

Em seguida crie o seguinte model:

# -*- encoding: utf-8 -*-
from django.db import models
from django.contrib import admin
import logging
 
class Log(models.Model):
    level = models.IntegerField(db_index=True)
    file = models.CharField(max_length=512, db_index=True)
    lineno = models.IntegerField()
    date = models.DateTimeField(db_index=True)
    message = models.TextField()
 
    def _get_level_name(self):
        return logging.getLevelName(self.level)
    levelName = property(fget=_get_level_name)
 
    def _get_message_summary(self):
        if len(self.message) > 100:
            return '%s...'%(self.message[:100])
        else:
            return self.message
    messageSummary = property(fget=_get_message_summary)
 
    def _get_file_summary(self):
        if len(self.file) > 30:
            return '...%s'%(self.file[-30:])
        return self.file
    fileSummary = property(fget=_get_file_summary)
 
class LogAdmin(admin.ModelAdmin):
   date_hierarchy = 'date'
   list_display = ('level', 'levelName', 'date','messageSummary', 'fileSummary', 'lineno')
   list_filter = ('level',)
   search_fields = ('message', 'file')
 
admin.site.register(Log, LogAdmin)
 

Em seguida crie o arquivo "handler.py" dentro do aplicativo "log" com o seguinte conteúdo:

 
# -*- encoding: utf-8 -*-
import logging
import datetime
from SEUPROJETO.log.models import Log
 
class DjangoHandler(logging.Handler):
    '''Executa a manipulação do log e insere no banco de dados'''
    def emit(self, record):
        log = Log()
        log.level = record.levelno
        log.file = record.pathname
        log.lineno = record.lineno
        log.message = record.msg
        # TODO: Utiizar o record.created
        log.date = datetime.datetime.now()
        log.save()
 

Com isso você já tem tudo que precisa pra logar direto pro banco de dados, só falta uma coisa: Configurar o projeto para o logging usar nosso handler.

Pra fazer isso, edite o arquivo __init__.py (e você achando que esse arquivo era inutil :) e adicione o seguinte conteúdo ao arquivo:

 
import logging
from SEUPROJETO.log.handler import DjangoHandler
django_handler = DjangoHandler()
logging.root.addHandler(django_handler)
 

E pronto, é só correr pro abraço, todo e qualquer log que você executar vai ser armazenado no banco de dados.

Yes! Tudo que faltava pra terminar meu projeto!
Yes! Tudo que faltava pra terminar meu projeto!

... e antes que você venha me reclamar que a p0rr@ do log não ta aparecendo em lugar nenhum, verifique se você está usando o logging.debug com a configuração padrão do módulo logging (que só exibe mensagens de nível mais alto).

Em tempo: Eu sei que é extremamente simples criar um módulo/pacote com tudo isso, mas não seria tão didatico simplesmente falar "baixe aqui, copie ali e import lá".

Se você tiver interesse, sugira a implantação deste módulo ao django.contrib ;)

API do Twitter para Python

Postado por Yoshio Iwamoto em 14/10/2009

Hoje vou mostrar como fazer uso da API do Twitter para Python, a Python Twitter API. Sua utilização é bem simples e podemos criar vários aplicativos ou scripts para automatizar algumas tarefas no microblog, como o script que fiz no meu último post.

Instalação no Linux
Baixe o código fonte da última versão aqui.

Descompacte com o comando:
$ tar -zxvf python-twitter-XXX.tar.gz

Após descompactar entre no diretório criado e execute o seguinte comando como usuário root:
# python setup.py install


Utilização
Para utilizar a API importe o módulo twitter:

import twitter
...

As principais classes que você deve conhecer são:
twitter.Api
twitter.User
twitter.Status
twitter.DirectMessage

Para iniciar, crie uma instancia da classe twitter.Api:

import twitter
api = twitter.Api()

Com este objeto você pode utilizar os métodos da API que não necessitam de autenticação do usuário. Um Exemplo é o método GetPublicTimeline, que sem parâmetros retorna as últimas 20 mensagens de status dos usuários.

import twitter
api = twitter.Api()
status_list = api.GetPublicTimeline()
for status in status_list:
    print status.user.name

No exemplo anterior o status é um objeto da classe twitter.Status. A classe twitter.Status possui um atributo user que é um objeto da classe twitter.User.

Para realizar a autenticação de um usuário, instancie a classe twitter.Api, porém passando o usuário e a senha como parâmetros:

import twitter
api = twitter.Api(username='joao', password='abc123')

Para enviar uma mensagem utilize o método PostUpdate:

# -*- encoding: utf-8 -*-
import twitter
api = twitter.Api(username='joao', password='abc123')
status = api.PostUpdate('''Yohohoho! Enviei uma mensagem! Mas cuidado
com os limite de 140 caracteres.''')

Repare que ele retorna o status da mensagem enviada.

Várias mensagens contínuas
Um método interessante da API é o PostUpdates, que permite que seja enviada uma mensagem com mais de 140 caracteres. A mensagem na verdade é enviada como se fosse várias mensagens com no máximo 140 caracteres.

Você também pode indicar uma string de continuação no segundo parâmetro, esta string é colocada no final das mensagens para indicar a continuação.

# -*- encoding: utf-8 -*-
import twitter
api = twitter.Api(username='joao', password='abc123')
status = api.PostUpdates('''Yohohoho! Enviei uma mensagem bem grande!
Agora você não precisa se preocupar com o tamanho da mensagem pois
este método irá dividi-la para você em várias mensagens, você também
pode utilizar uma string de continuação ao lado.''', '…')

Obs: Segundo a documentação da API, o Twitter remove as reticências ("...") das strings das mensagem, por isso utilize o caractere UNICODE \u2026 ("…"). Também não ultrapasse o limite dos 150 requests permitidos por hora pelo Twitter.

Seja seguido no Twitter sem incomodar as pessoas

Postado por Yoshio Iwamoto em 7/10/2009

Em dois dias meu usuário doTwitter pulou de 20 seguidores para quase 200. Não é enganação, é até um problema do Twitter, ou não, já que não é bem um bug.

Se você procurar por aí na internet irá encontrar vários métodos de como conseguir mais seguidores no Twitter, mas todos dizem praticamente a mesma coisa: seguir os outros e esperar que eles te sigam também.

De fato isto é verdade e funciona se você seguir muitos (muitos) usuários, mas minha idéia foi um pouco diferente. Vou contar uma historinha.

Estava vendo na Folha Online uma matéria sobre as principais frases ditas pelos famosos no Twitter e umas das frases era do ilustre William Bonner (que aliás sou grande fã). Eu já esqueci qual foi a frase dele, mas o importante é que graças a matéria eu descobri que ele tinha Twitter (@realwbonner), então passei a segui-lo.

Por curiosidade fui ver quantos seguidores ele tinha e ao entrar na página de seguidores dele meu usuário do Twitter estava sendo exibido no topo dos resultados.

Naquele dia, acho que ele tinha mais ou menos 40 mil seguidores. A exibição do meu usuário na página de seguidores dele acabou me rendendo 3 novos seguidores. Uma idéia estava surgindo...

Entrei novamente na página de seguidores dele, mas meu usuário não estava mais no topo. A causa era que o @realwbonner estava adquirindo mais seguidores fazendo os antigos caírem nos resultados. Uma idéia se completou!

Eureka! Vou criar um script para dar Unfollows e Follows nos Twitters com mais usuários do Brasil. Em tempos em tempos eu executo o script e ele faz o meu usuário ficar no topo dos resultados dos seguidores deles.

Se pegarmos o @hucklucianO que possui mais de 1 milhão de seguidores e deixar o seu usuário em exibição no topo da página de seguidores dele, isto irá fazer as pessoas prestarem mais atenção em você.

Vamos ao script

O script foi desenvolvido em Python (v2.6) e utiliza a Python Twitter API (v0.6).

Baixe o código fonte da Python Twitter API em:
http://python-twitter.googlecode.com/files/python-twitter-0.6.tar.gz

Descompacte com o arquivo com o comando:
$ tar -zxvf python-twitter-0.6.tar.gz

Entre na pasta criada e instale a API (como root):
$ cd python-twitter-0.6
$ sudo python setup.py install

Finalmente, baixe o script que criei aqui. Será necessário edita-lo. Abra com algum editor de texto e altere este trecho:

your_users = [
    ('seu_usuario', 'senha',), # Ex: ('joao', 'asd123'),
    # ('outro usuario', 'senha'),
    # ...
]

No trecho acima você deve inserir o seu usuário e senha do Twitter para que a API possa realizar o login. Você está de posse de 100% do código, repare que em momento algum o seu usuário e senhas são enviados para mim. :D

Neste outro trecho você insere os usuário do Twitter que deseja seguir. Coloque cada usuário em uma linha dentro do espaço delimitado entre as três aspas. No script eu já adicionei alguns camaradas :)

twitter_users = '''
yoshioiwamoto
rafaelsdm
ricardoperez
gabrielverta
'''

Quanto mais seguidores eles tiverem, melhor. Uma dica é dar uma passada no twittercounter onde você pode encontrar quem são os usuários mais seguidos no mundo ou em um país específico (Brasil).

Para rodar o script execute na linha de comando:
$ python followme.py

No meu usuário @yoshioiwamoto eu precisei seguir os 15 usuários do Twitter mais seguidos do Brasil e o script era rodado 3 vezes ao dia.

Uma informação importante, para cada usuário que você segue são necessários 2 requests e o Twitter possui um limite de 150 requests por hora, então gerencie bem os uso deste script.

Se você utiliza sistemas operacionais proprietários que não são baseados em Unix, aguarde até que uma boa alma crie um tutorial para você. :D

Acessando `block` tags parentes em templates Django

Postado por Rafael Sierra em 16/12/2008

Se tem algo que eu admiro muito no sistema de templates do Django, é a tag block, eu acho ela realmente f#!$ pra ca#@!&.

Só que recemente eu descobri algo nela que se eu estivesse em um ato sexual teria resultado em um fork(), que é a possibilidade de acessar o conteúdo antigo da tag antes dela ser sobrescrevida por você.

É extremamente simples, vamos pegar como exemplo o seguinte template `base.html`:

 
<html>
    <head><title>{% block title%}Meu site dahora{% endblock %}</html>
    <body>{% block content %}{% endblock %}
</html>
 

A parte legal fica por conta do bloco title. Até então, sempre que eu quizesse colocar "Meu site dahora | Home" no titulo, eu teria que fazer assim em um template filho:

 
{% extends "base.html" %}
{% block title %}Meu site dahora | Home{% endblock %}
 

O problema óbvio nesse caso, é que se um dia eu resolver trocar o titulo pra "O Jardineiro é Jesus", então eu vo ter que editar todo template que extende o template `base.html` pra arrumar isso.

Eis então que surge a solução

 
{% extends "base.html" %}
{% block title %}{{block.super}} | Home{% endblock %}
 

:D Simples e funcional. VIDA LONGA AO DJANGO!

Av. Conselheiro Nébias, 368A, Cj. 413
Vila Mathias - Santos - SP
Telefone: (13) 3345-4580

© 2008 - 2009 Stiod. Todos os direitos reservados.