quarta-feira, abril 15, 2009

13 passos simples para termos o Django no Google App Engineprot

Este sensacional tutorial é uma tradução do artigo Django on Google App Engine in 13 simple steps, escrito por Thomas Brox Røst.

Neste tutorial eu mostrarei como ter uma aplicação simples com acesso a banco de dados usando Django e rodando no Google App Engine. Assumirei que você tem alguma familiaridade com o Django.

Passo 1: Registre um nome de aplicativo e instale o kit de desenvolvimento seguindo as instruções do site.

Passo 2: Crie um diretório para o seu aplicativo - Para este tutorial meu aplicativo chama-se mashname:
tmp$ mkdir mashname
tmp$ cd mashname
Passo 3: Adicione um arquivo chamado main.py no seu novo diretório:
# main.py

import os, sys
os.environ["DJANGO_SETTINGS_MODULE"] = "mashname.settings"
sys.path.append("/home/brox/tmp/mashname")

# Google App Engine imports.
from google.appengine.ext.webapp import util

# Force Django to reload its settings.
from django.conf import settings
settings._target = None

import django.core.handlers.wsgi
import django.core.signals
import django.db
import django.dispatch.dispatcher

# Log errors.
#django.dispatch.dispatcher.connect(
#   log_exception, django.core.signals.got_request_exception)

# Unregister the rollback event handler.
django.dispatch.dispatcher.disconnect(
django.db._rollback_on_exception,
django.core.signals.got_request_exception)

def main():
# Create a Django application for WSGI.
application = django.core.handlers.wsgi.WSGIHandler()

# Run the WSGI CGI handler with that application.
util.run_wsgi_app(application)

if __name__ == "__main__":
main()
Este é basicamente o mesmo arquivo sugerido, exceto pelo caminho do Python que eu tive que configurar para poder fazer os testes localmente. Eu também tive que configurar a variável DJANGO_SETTINGS_MODULE - pode ser que este passo seja desnecessário quando o aplicativo estiver executando no App Engine. Eu tive que desabilitar o log de erros, os quais eu não consegui fazer funcionar.

Passo 4: Adicione um arquivo chamado app.yaml ao mesmo diretório com o conteúdo abaixo:
application: mashname
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
script: main.py
Assegure-se de usar o nome correto do aplicativo.

Passo 5: Do seu diretório mashname, crie um novo projeto do Django:
tmp/mashname$ django-admin.py startproject mashname

(Estou assumindo que o seu diretório do Django está configurado e funcionando como deveria.)

Passo 6: Agora você deveria poder testar seu aplicativo:
tmp/mashname$ cd ..
tmp$ dev_appserver.py mashname
INFO     2008-04-08 19:08:10,023 appcfg.py] Checking for updates to the SDK.
INFO     2008-04-08 19:08:10,384 appcfg.py] The SDK is up to date.
INFO     2008-04-08 19:08:10,404 dev_appserver_main.py] Running application mash
name on port 8080: http://localhost:8080
Aponte o seu browser para o endereço http://127.0.0.1:8080/ e você deverá ver a mensagem padrão do Django "It worked!".

Passo 7: Crie um aplicativo Django dentro do projeto:
tmp$ cd mashname
tmp/mashname$ python mashname/manage.py startapp main
Passo 8: Agora é hora de adicionarmos um modelo. Nós criaremos um aplicativo simples que loga todos os visitantes em uma base de dados e exibe seus endereços IP. Edite o arquivo ~/mashname/mashname/main/models.py para que ele se pareça com isso:
# models.py

from google.appengine.ext import db

class Visitor(db.Model):
ip = db.StringProperty()
added_on = db.DateTimeProperty(auto_now_add=True)
Não há necessidade de sincronizarmos o banco de dados uma vez que não estaremos usando os modelos do próprio Django.

Passo 9: Agora nós criaremos uma view que é responsável tanto por adicionar os dados ao modelo Visitor quanto por mostrar os visitantes anteriores. Edite o arquivo views.py (no mesmo diretório em que está o arquivo models.py) de modo que ele faça o que queremos:
# views.py

from django.http import HttpResponse

from mashname.main.models import Visitor

def main(request):
visitor = Visitor()
visitor.ip = request.META["REMOTE_ADDR"]
visitor.put()

result = ""
visitors = Visitor.all()
visitors.order("-added_on")

for visitor in visitors.fetch(limit=40):
result += visitor.ip + u" visited on " + unicode(visitor.added_on) + u""

return HttpResponse(result)

Passo 10: Finalmente, faça com que o seu arquivo urls.py aponte para a view:
# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns("",
(r"^$", "mashname.main.views.main"),
)
Passo 11: Teste o seu aplicativo (do mesmo modo que foi feito no passo 6) e tudo deveria funcionar perfeitamente. A cada vez que a página for recarregada uma nova entrada será adicionada ao modelo Visitor model e será exibido na view.

Passo 12: Faça o upload do seu aplicativo para o Google App Engine:
tmp$ appcfg.py update mashname
Na primeira vez em que o upload for feito, você terá que informar seu e-mail e sua senha do google.

Passo 13: Divirta-se! Para ver o resultado final, vá para http://adf.ly/35ZNC.

terça-feira, abril 14, 2009

Resolvendo erro de conexao no MySQL

Um caso muito comum para quem vai usar o mysql é: criar o banco de dados, criar o usuário que terá acesso aos objetos desta base e por fim dar as permissões de acesso ao mesmo.

Aí, ao tentarmos conectar na base não conseguimos e o mysql exibe o erro
ERROR 1045 (28000): Access denied for user 'dbuser'@'localhost' (using password: YES)
ou
ERROR 1045 (28000): Access denied for user 'dbuser'@'localhost' (using password: NO)
dependendo de termos fornecido ou não uma senha para o usuário.

Com o resolver isso?

Supondo que a base seja a dbtest e que o usuário do banco se chame dbuser. Provavelmente tu o criaste assim:

SET PASSWORD FOR dbuser = PASSWORD("dbpassword");
E aí tu deste os direitos de acesso à base desse jeito:
GRANT ALL PRIVILEGES ON dbtest.* TO dbuser IDENTIFIED BY 'dbpassword';
O problema é que para que o usuário se conecte a partir do um host qualquer, tu deves explicitamente fornecer permissões à ele.

Ou seja, as permissões de acesso devem ser dadas por host. Todos os acessos a partir de endereços que não tenham sido explicitamente permitidos serão negados.

Assim, para permitir que o usuário dbuser se conecte ao banco a partir do computador local (localhost), o comando a ser dado é:
GRANT ALL PRIVILEGES ON dbtest.* to dbuser@localhost identified by "dbpassword";
ou
GRANT ALL PRIVILEGES ON dbtest.* to dbuser@localhost;
dependendo do fato do usuário ter senha ou não.

Tu podes obter mais informações sobre como usar o mysql com qualquer um destes livros aqui.

Agora, se for para comprar apenas um livro, o que vai responder a TODAS as tuas dúvidas, recomendo o MySQL: a Bíblia, do Steve Suehring.

Espero que este artigo te ajude.

Usando Mutt com GMail

O Gmail é o melhor serviço de e-mail e o Firefox é o melhor browser. Mas, se tu mantiveres a página do Gmail aberta por um longo período, o Firefox consumirá muita memória do teu computador.

Se tu tens uma máquina antiga como a minha, tu sabes que cada byte é importante. Assim, eu decidi voltar a usar meu antigo cliente de e-mail: mutt (http://www.mutt.org/).

Aqui eu mostro os passos que tu precisas fazer para que o mutt possa acessar o Gmail usando o protocolo IMAP.

Eu estou usando o Ubuntu 7.04 com o mutt 1.5.13, mas o que for dito aqui deve funcionar com qualquer distribuição.

Tu deves substituir meu_email@gmail.com e minha_senha com o teu e-mail e senha do GMail.

  1. Primeiro tu tens que habilitar o acesso via IMAP para a tua conta do Gmail. Para habilitar o IMAP faça assim:
    1.1. Logue na tua conta do Gmail.
    1.2. Clique em Configurações no topo da página do Gmail.
    1.3. Clique Encaminhamento POP/IMAP.
    1.4. Selecione Ativar IMAP.

  2. Instale o mutt, o msmtp and o ssl. Não vou mostrar como fazer isso porque este passo é diferente para cada distribuição.

  3. Crie o arquivo de configuração do msmtp (~/.msmtprc) como mostrado abaixo:

    account default
    host smtp.gmail.com
    port 587
    from meu_email@gmail.com
    tls on
    tls_starttls on
    auth on
    user meu_email@gmail.com
    password minha_senha
    logfile ~/.msmtp.log

  4. Create mutt configuration file (~/.muttrc) as shown:

    set imap_user = "meu_email@gmail.com"
    set imap_pass = "minha_senha"

    set from = "meu_email@gmail.com"
    set realname = "Teu Nome verdadeiro"

    set folder = "imaps://imap.gmail.com:993"
    set spoolfile = imaps://imap.gmail.com:993/INBOX
    set record=""
    set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"

    set header_cache="~/.mutt/cache/headers"
    set message_cachedir="~/.mutt/cache/bodies"
    set certificate_file=~/.mutt/certificates
    set move = no
    set imap_check_subscribed="yes"
    set imap_list_subscribed="yes"
    set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
    # esta linha instrui o mutt a fazer o refresh da minha caixa de entrada a cada 60 segundos
    set mail_check=60
    #Estou usando o character ^ para dizer para o mutt atualizar imediatamente a lista de e-mails.
    bind index "^" imap-fetch-mail

Isso é tudo.

segunda-feira, abril 06, 2009

Organize os seus modelos no Simulink

No post Como gerar Diagramas de Bode sem fazer contas no MATLAB eu mostrei uma das inúmeras facilidades que esta ferramenta nos fornece. Neste, vou mostrar como podes tornar teu modelo mais organizado com o uso de blocos.

Não fui claro? Então deixe-me explicar melhor.

Durante o desenvolvimento dos nossos modelos no Simulink, junto com o progresso da modelagem ocorre o progresso na bagunça.

Por exemplo, a figura 1 ilustra um modelo de tanque com medidor de volume desperdiçado (líquido que vazou).

Figura 1 - Diagrama com múltiplos blocos

Este diagrama, apesar de pequeno, mostra vários blocos (8, para ser mais exato). Como poderíamos tornar este modelo mais legível?

Simples. Vamos agrupar os blocos que correspondem a uma única função em uma única caixa.

No exemplo acima, os blocos Integrador, somador, Volume Total do Tanque e o bloco limitador formam, na realidade, um totalizador de vazão. Então, nada mais natural que representá-los como um único equipamento.

Para fazer isso, deves proceder assim:

1 - selecione os blocos que queres transformar um uma única caixa
2 - clique com o botão direito do mouse sobre qualquer um dos componentes selecionados. Abrirá um popup com várias ações.
3 - Selecione a opção Create Subsystem (ver figura 2).

Figura 2 - Selecionando objetos para gerar o bloco equivalente.

No lugar de todos aqueles blocos selecionados aparecerá um único, conforme mostrado na figura 3.

Figura 3 - Bloco equivalente após a criação do subsistema.

Na figura 3 podemos ver que a entrada e a saída do bloco chamam-se, respectivamente, In1 e Out1 (se houvesse mais de uma entrada e/ou saída, teríamos In2, In3,... e Out2, Out3, ...).

Ok. Para tornar mais intuitivo o que este bloco equivalente representa, vamos fazer mais algumas modificações no modelo:

1 - renomearemos o bloco de Subsystem para algo que represente melhor o que ele faz. Para isso, clique sobre o texto Subsystem e o substitua por Totalizador de Vazão.

2 - In1 e Out1 não dizem muita coisa. Vamos renomeá-los para algo que tenha algum significado para nós. Dê um duplo clique sobre o bloco que acabamos de criar. Abrirá uma janela mostrando seu interior, ou seja, os blocos que o constituem. A figura 4 ilustra o que acabei de dizer.

Figura 4 - Vista explodida do bloco Totalizador de Vazão.

Agora é só clicar sobre os textos In1 e Out1 e substituí-los por outro texto do teu interesse. Eu vou renomear In1 para Qe (vazão de entrada) e Out1 para Volume_Vazamento. A figura 5 mostra o resultado final.

Figura 5 - Modelo simplificado

Para um projeto pequeno como o demostrado neste artigo, o trabalho parece não valer a pena. mas acredite, conforme tu fores melhorando teu modelo, mais e mais blocos surgirão. Aí sim verás a necessidade e a utilidade desta técnica.

O melhor de tudo é que podes continuar com este processo indefinidamente, fazendo com que os blocos gerados sejam agrupados em outros blocos, reduzindo ainda mais o circuito.

Do mesmo modo que no post Como gerar Diagramas de Bode sem fazer contas no MATLAB, recomendo que leias pelo menos um dos livros abaixo: