Lançado o novo Tempo Real do Globoesporte.com versão Iphone

Posted July 23rd, 2009 in Projetos by felipepavao

Globoesporte Tempo Real Iphone - Tela de Cobertura

Ontem fizemos os últimos testes e colocamos em produção nosso aplicativo web para Iphone de cobertura em tempo real dos jogos de futebol. O aplicativo tem características semelhantes ao original do Globoesporte.com, entretanto, respeita os padrões de desenvolvimento para sites visualizados em dispositivos móveis. Basicamente ele consome as mesmas informações publicadas no aplicativo web Tempo Real original, porém as exibe em um formato customizado para Iphone.

Na verdade, nós já tinhamos esse aplicativo funcionando em uma arquitetura antiga, sob Java + Struts + Jbossweb + Oracle atrelado a todo o conglomerado de sites móveis da Globo.com. O problema é que o aplicativo de Tempo Real, devido ao grande apelo que é futebol, recebia uma grande quantidade de acessos simultâneos, causando lentidão em todos os outros sites.

Globoesporte Tempo Real Iphone - Tela de Escalação

Sugerimos então refazer apenas o aplicativo de Tempo Real, retirando-o da arquitetura antiga e adicionando algumas correções de bug e features, mas desta vez sob a nova arquitetura. Decidimos por Python + Django pois é a direção que a empresa vem adotando para construir novos sites e aplicativos. Com a ajuda do SCRUM, conseguimos refazer todo o aplicativo em tempo (1 sprint), além de entregarmos outras histórias em paralelo, pois aqui na Globo.com, devido ao número de demandas, temos que trabalhar simultaneamente em diversos produtos.

Globoesporte Tempo Real Iphone - Tela de Vídeos

Gostaria de parabenizar a todos do time e espero anunciar neste humilde blog novidades em breve.

Tratando data de RSS com Django templates

Posted June 19th, 2009 in Desenvolvimento by felipepavao

O sistema de templates do Django permite a criação de tags e filtros para que possamos formatar ou tratar o conteúdo em um template de acordo com nosso desejo. (Veja mais na documentação do Django). Devido a filosofia do framework, é muito fácil criar um novo filtro para um tratamento específico. E foi exatamente isso que precisamos fazer.

A tarefa consistia em fazer uma simples formatação de data. Esta data estava no formato GMT (Ex: Sun, 19 May 2002 15:21:36 GMT) e precisávamos recuperar apenas a hora e o minuto (Ex: 15h21). Aparentemente, seria fácil fazer a conversão, utilizando a função strptime da classe datetime. Esta função transforma uma string em data, através da equiparação do formato da data.

from datetime import *
rss_date = "Sun, 19 May 2002 15:21:36 GMT"
date_format = "%a, %d %b %Y %H:%M:%S %z"
new_date = datetime.strptime(rss_date, date_format)
 
##ERRO
##ValueError: 'z' is a bad directive in format '%a, %d %b %Y %H:%M:%S %z'

Como podemos ver no erro destacado, ao utilizarmos essa função, há um problema de reconhecimento do atributo %z, responsável pela representação do fuso horário, apesar de constar da documentação oficial. Verificamos o arquivo /usr/lib/python2.5/_strptime.py e identificamos que a classe não implementa este atributo. Após uma breve pesquisa no Google, identificamos que possivelmente  na versão 2.6  o parâmetro já esteja sendo suportado, mas ainda não fomos a fundo nessa questão. E como precisamos usar Python 2.5, resolvemos partir para uma nova e simples solução, que era apenas parsear a string pela posição dos caracteres.

@register.filter
def rss_date(value):
    return value[17:19] + "H|" + value[20:22]

O código acima registra um filtro para ser usado no template HTML. Não achamos que essa seja a solução ideal, mas devido ao problema de versão optamos por utilizá-la. Veja a seguir como utilizar no template.

{{item.date | rss_date}}

Testes de Django Middleware

Posted March 18th, 2009 in Desenvolvimento by felipepavao

Ainda não consegui parar e escrever sobre Rails aqui no blog, mas tenho descoberto coisas interessantes de Django. O novo desafio, aqui no trabalho, foi criar e testar um Middleware que tinha a função de identificar o User-Agent de um request e setar alguns parâmetros para que a aplicação pudesse se desenvolver a partir daí. É mais ou menos parecido com o que já foi mencionado aqui, anteriormente.

from django.conf import settings
from app.pub.structure import *
from django import http
import re
 
class IdentifyMiddleware(object):
 
    def process_request(self, request):
 
        # LIST PERFIS
        perfil = Perfil()
        perfis = perfil.all()
 
        for p in perfis:
            if p.regular_expression:
                logging.info("Identify User: regexp [%s]" % p.regular_expression)
                r = re.compile(p.regular_expression, re.IGNORECASE)
                if r.search(request.META['HTTP_USER_AGENT']):
                    request.perfil = p
                    return
 
        # SET PERFIL NONE
        perfil.name = "none"
        request.perfil = perfil

Esse Middleware lista expressões regulares guardadas em um banco de dados e compara com o User-Agent do request. Uma vez encontrada, é setado uma propriedade no request chamada perfil, identificando assim o tipo de request que estamos trabalhando. O teste realizado no Middleware era verificar se o request realmente trazia o parâmetro perfil setado.

#!/usr/bin/python
# vim: ai ts=4 sts=4 et sw=4
 
import unittest
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
#from django.test import TestCase
from django.http import HttpRequest
from app.handset.identify import IdentifyMiddleware
from django.conf import settings
 
class TestIdentify(unittest.TestCase):
 
    def _get_request(self, path):
        request = HttpRequest()
        request.META = {
            'SERVER_NAME': settings.CDA_URL
        }
 
        request.path = path_info = "/%s" % path
        return request
 
    def testPerfilIphone(self):
        request = self._get_request('identify')
        request.META = {
                        'HTTP_USER_AGENT':'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A538a Safari/419.3'
                        }
        IdentifyMiddleware().process_request(request)
        self.assertEquals(request.perfil.name, 'IPhone')
 
    def testPerfilStandard(self):
        request = self._get_request('identify')
        request.META = {
                        'HTTP_USER_AGENT':'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.7) Gecko/2009030422 Ubuntu/8.10 (intrepid) Firefox/3.0.7'
                        }
        IdentifyMiddleware().process_request(request)
 
        self.assertEquals(request.perfil.name, 'standard')
 
if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestIdentify)
    unittest.TextTestRunner(verbosity=2).run(suite)

O teste por si só se explica, mas vale salientar o ponto onde foi utilizado a biblioteca HttpRequest do próprio Django para montar o request. Outro ponto é quando o teste instancia o método IdentifyMiddleware().process_request(request) do Middleware, o parâmetro request se mantem por referência, não necessitando de um retorno (return alguma coisa) do Middleware para continuar a testar o parâmetro perfil adicionado ao request.

Com certeza o próximo texto será sobre Rails, que é um framework que voltei a estudar muito para desenvolver projetos pessoais. Até lá.

Blog sobre Rails, Django e internet

Posted March 11th, 2009 in Projetos by felipepavao

Como sabem, sou a pessoa  responsável pelo projeto BlogFactory e pelas postagem no Blog da Fábrica. E ultimamente, por estar estudando muitas tecnologias diferentes, senti a necessidade de registrar minhas observações e compartilhar com a comunidade esse conhecimento. Surgiu então o StartAPP.org com layout simples e objetivo. Optamos por utilizar um layout padrão encontrado no repositório do WordPress para que a ideia deste novo projeto não ficasse na gaveta. Mas já estamos trabalhando em algumas customizações para dar uma identidade visual única ao projeto.

Portanto, quem tiver interesse em trocar ideias sobre software, internet, Rails, Django, não deixe de conferir o StartAPP.org.

Aplicações web Iphone e Django

Posted February 18th, 2009 in Desenvolvimento by felipepavao

Para os que não sabem, eu trabalho desenvolvendo sites para dispositivos móveis (celulares e smarthphones) na Globo.com, e no último projeto que utilizamos o Django, precisávamos desenvolver um identificador de User Agent. Este identificador direcionaria a renderização de templates para o endereço correto onde os arquivos customizados se encontravam, pois fizemos templates específicos para os aparelhos portáteis da Apple.

Seguindo a linha do Django e após algumas pesquisas, encontramos um Middleware que resolvia a questão.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.conf import settings
import re
 
class iPhoneMiddleware(object):
    """
    If the Middleware detects an iPhone/iPod the template dir changes to the
    iPhone template folder.
    """
 
    def __init__(self):
        self.normal_templates = settings.TEMPLATE_DIRS
        self.iphone_templates = (settings.TEMPLATE_DIRS[0] + '/iphone',)
 
    def process_request(self, request):
        p = re.compile('iPhone|iPod', re.IGNORECASE)
        if p.search(request.META['HTTP_USER_AGENT']):
            # user agent looks like iPhone or iPod
            settings.TEMPLATE_DIRS = self.iphone_templates
        else:
            # other user agents
            settings.TEMPLATE_DIRS = self.normal_templates
        return

O código é muito explicativo, mas vale denotar o ponto chave, quando o script executa a expressão regular procurando pelas palavras “iPhone|iPod” vindas do parâmetro “User Agent”, ele altera o endereço padrão dos templates para a pasta padrão ou para o path + “/iphone”.
Está aí a mágica do negócio.

A função do Middleware para o Django

Posted February 17th, 2009 in Desenvolvimento by felipepavao

Apesar de preferir utilizar em meus projetos pessoais o Rails, tenho estudado e trabalhado muito com o Django. E uma das características mais legais que eu encontrei foi a questão dos Middlewares.

Em comparação com o Rails, seria como um filtro (:before_filter por exemplo) que executaria um comportamento antes da ação principal. O Middleware também tem essa função no Django: é executado antes do processamento da view (que no Rails seria o controller). Veja na imagem como é processado um request com a utilização de Middlewares:

1
2
3
4
5
6
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware',
)

Processamento de um request no Django

Este trecho de código fica declarado no arquivo de configurações do Django. Ele indica a ordem como os Middlewares serão executados. Essa abordagem nos traz a facilidade de incluir uma série de comportamentos antes de ter um método da view executado.